solidus_bactracs 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gem_release.yml +2 -2
- data/.github/CODEOWNERS +54 -0
- data/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +3 -0
- data/.github/workflows/release.yml +50 -0
- data/.gitignore +0 -2
- data/.rubocop_todo.yml +3 -3
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +7 -1
- data/PULL_REQUEST_TEMPLATE.md +3 -0
- data/README.md +5 -5
- data/app/assets/javascripts/spree/backend/{solidus_backtracs.js → solidus_bactracs.js} +0 -0
- data/app/assets/javascripts/spree/frontend/{solidus_backtracs.js → solidus_bactracs.js} +0 -0
- data/app/assets/stylesheets/spree/backend/{solidus_backtracs.css → solidus_bactracs.css} +0 -0
- data/app/assets/stylesheets/spree/frontend/{solidus_backtracs.css → solidus_bactracs.css} +0 -0
- data/app/controllers/spree/{backtracs_controller.rb → bactracs_controller.rb} +9 -9
- data/app/decorators/models/{solidus_backtracs → solidus_bactracs}/spree/shipment_decorator.rb +5 -5
- data/app/helpers/{solidus_backtracs → solidus_bactracs}/export_helper.rb +2 -2
- data/app/jobs/{solidus_backtracs → solidus_bactracs}/api/schedule_shipment_syncs_job.rb +7 -7
- data/app/jobs/{solidus_backtracs → solidus_bactracs}/api/sync_shipment_job.rb +1 -1
- data/app/jobs/{solidus_backtracs → solidus_bactracs}/api/sync_shipments_job.rb +3 -3
- data/app/queries/{solidus_backtracs → solidus_bactracs}/shipment/between_query.rb +1 -1
- data/app/queries/{solidus_backtracs → solidus_bactracs}/shipment/exportable_query.rb +3 -3
- data/app/queries/{solidus_backtracs → solidus_bactracs}/shipment/pending_api_sync_query.rb +6 -6
- data/app/views/spree/{backtracs → bactracs}/export.xml.builder +5 -5
- data/bin/console +1 -1
- data/bin/rails-engine +1 -1
- data/bin/sandbox +1 -1
- data/config/routes.rb +2 -2
- data/db/migrate/{20210220093010_add_backtracs_api_sync_fields.rb → 20210220093010_add_bactracs_api_sync_fields.rb} +2 -2
- data/lib/generators/{solidus_backtracs → solidus_bactracs}/install/install_generator.rb +3 -3
- data/lib/generators/{solidus_backtracs → solidus_bactracs}/install/templates/initializer.rb +42 -12
- data/lib/solidus_backtracs/version.rb +1 -1
- data/lib/{solidus_backtracs → solidus_bactracs}/api/batch_syncer.rb +5 -5
- data/lib/{solidus_backtracs → solidus_bactracs}/api/client.rb +4 -4
- data/lib/{solidus_backtracs → solidus_bactracs}/api/rate_limited_error.rb +1 -1
- data/lib/{solidus_backtracs → solidus_bactracs}/api/request_error.rb +1 -1
- data/lib/solidus_bactracs/api/request_runner.rb +135 -0
- data/lib/{solidus_backtracs → solidus_bactracs}/api/shipment_serializer.rb +28 -27
- data/lib/{solidus_backtracs → solidus_bactracs}/api/threshold_verifier.rb +6 -6
- data/lib/{solidus_backtracs → solidus_bactracs}/configuration.rb +4 -4
- data/lib/{solidus_backtracs → solidus_bactracs}/engine.rb +2 -2
- data/lib/{solidus_backtracs → solidus_bactracs}/errors.rb +1 -1
- data/lib/{solidus_backtracs → solidus_bactracs}/shipment_notice.rb +2 -2
- data/lib/{solidus_backtracs → solidus_bactracs}/testing_support/factories.rb +0 -0
- data/lib/solidus_bactracs/version.rb +5 -0
- data/lib/solidus_bactracs.rb +16 -0
- data/solidus_bactracs.gemspec +3 -2
- data/spec/controllers/spree/{backtracs_controller_spec.rb → bactracs_controller_spec.rb} +9 -9
- data/spec/fixtures/{backtracs_xml_schema.xsd → bactracs_xml_schema.xsd} +0 -0
- data/spec/jobs/{solidus_backtracs → solidus_bactracs}/api/schedule_shipment_syncs_job_spec.rb +5 -5
- data/spec/jobs/{solidus_backtracs → solidus_bactracs}/api/sync_shipments_job_spec.rb +10 -10
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/batch_syncer_spec.rb +28 -28
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/client_spec.rb +10 -10
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/rate_limited_error_spec.rb +1 -1
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/request_error_spec.rb +1 -1
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/request_runner_spec.rb +3 -3
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/shipment_serializer_spec.rb +1 -1
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/api/threshold_verifier_spec.rb +9 -9
- data/spec/lib/{solidus_backtracs → solidus_bactracs}/shipment_notice_spec.rb +4 -4
- data/spec/lib/solidus_bactracs_spec.rb +9 -0
- data/spec/models/spree/shipment_spec.rb +2 -2
- data/spec/queries/{solidus_backtracs → solidus_bactracs}/shipment/between_query_spec.rb +1 -1
- data/spec/queries/{solidus_backtracs → solidus_bactracs}/shipment/exportable_query_spec.rb +1 -1
- data/spec/queries/{solidus_backtracs → solidus_bactracs}/shipment/pending_api_sync_query_spec.rb +4 -4
- data/spec/spec_helper.rb +2 -2
- data/spec/support/configuration_helper.rb +1 -1
- metadata +72 -64
- data/lib/solidus_backtracs/api/request_runner.rb +0 -109
- data/lib/solidus_backtracs.rb +0 -16
- data/spec/lib/solidus_backtracs_spec.rb +0 -9
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
SolidusBactracs.configure do |config|
|
4
4
|
# Choose between Grams, Ounces or Pounds.
|
5
5
|
config.weight_units = "Grams"
|
6
6
|
|
7
|
-
# Capture payment when
|
7
|
+
# Capture payment when Bactracs notifies a shipping label creation.
|
8
8
|
# Set this to `true` and `Spree::Config.require_payment_to_ship` to `false` if you
|
9
9
|
# want to charge your customers at the time of shipment.
|
10
10
|
config.capture_at_notification = false
|
@@ -13,8 +13,8 @@ SolidusBacktracs.configure do |config|
|
|
13
13
|
config.api_base = ENV['BACKTRACS_API_BASE'] || 'https://bactracstest.andlor.com'
|
14
14
|
config.api_retries = ENV['BACKTRACS_API_RETRIES'] || 3
|
15
15
|
|
16
|
-
#
|
17
|
-
# Set the username and password you desire for
|
16
|
+
# Bactracs expects the endpoint to be protected by HTTP Basic Auth.
|
17
|
+
# Set the username and password you desire for Bactracs to use.
|
18
18
|
config.webhook_username = "smoking_jay_cutler"
|
19
19
|
config.webhook_password = "my-awesome-password"
|
20
20
|
|
@@ -42,14 +42,14 @@ SolidusBacktracs.configure do |config|
|
|
42
42
|
####### XML integration
|
43
43
|
# Only uncomment these lines if you're going to use the XML integration.
|
44
44
|
|
45
|
-
# Export canceled shipments to
|
45
|
+
# Export canceled shipments to Bactracs
|
46
46
|
# Set this to `true` if you want canceled shipments included in the endpoint.
|
47
47
|
# config.export_canceled_shipments = false
|
48
48
|
|
49
49
|
# You can customize the class used to receive notifications from the POST request
|
50
50
|
# Make sure it has a class method `from_payload` which receives the notification hash
|
51
51
|
# and an instance method `apply`
|
52
|
-
# config.shipment_notice_class = '
|
52
|
+
# config.shipment_notice_class = 'SolidusBactracs::ShipmentNotice'
|
53
53
|
|
54
54
|
####### API integration
|
55
55
|
# Only uncomment these lines if you're going to use the API integration.
|
@@ -58,21 +58,21 @@ SolidusBacktracs.configure do |config|
|
|
58
58
|
# that responds to `#call`. At the very least, you'll need to uncomment the
|
59
59
|
# following lines and customize your store ID.
|
60
60
|
# config.api_shipment_serializer = proc do |shipment|
|
61
|
-
#
|
61
|
+
# SolidusBactracs::Api::ShipmentSerializer.new(store_id: '12345678').call(shipment)
|
62
62
|
# end
|
63
63
|
|
64
|
-
# Override the logic used to match a
|
64
|
+
# Override the logic used to match a Bactracs order to a shipment from a
|
65
65
|
# given collection. This can be useful when you override the default serializer
|
66
66
|
# and change the logic used to generate the order number.
|
67
|
-
# config.api_shipment_matcher = proc do |
|
68
|
-
# shipments.find { |shipment| shipment.number ==
|
67
|
+
# config.api_shipment_matcher = proc do |bactracs_order, shipments|
|
68
|
+
# shipments.find { |shipment| shipment.number == bactracs_order['orderNumber'] }
|
69
69
|
# end
|
70
70
|
|
71
|
-
# API key and secret for accessing the
|
71
|
+
# API key and secret for accessing the Bactracs API.
|
72
72
|
# config.api_key = "api-key"
|
73
73
|
# config.api_secret = "api-secret"
|
74
74
|
|
75
|
-
# Number of shipments to import into
|
75
|
+
# Number of shipments to import into Bactracs at once.
|
76
76
|
# If unsure, leave this set to 100, which is the maximum
|
77
77
|
# number of shipments that can be imported at once.
|
78
78
|
config.api_batch_size = 100
|
@@ -90,3 +90,33 @@ SolidusBacktracs.configure do |config|
|
|
90
90
|
Sentry.capture_exception(error, extra: context)
|
91
91
|
}
|
92
92
|
end
|
93
|
+
|
94
|
+
class Spree
|
95
|
+
class Shipment
|
96
|
+
def normalize_valid_variants_from_bundles
|
97
|
+
self.line_items.reduce([]) do |variants, line_item|
|
98
|
+
if line_item.product.respond_to?(:assembly?) && line_item.product.assembly?
|
99
|
+
variants += line_item.product.parts.reject(&:invalid_part?)
|
100
|
+
else
|
101
|
+
variants << line_item.variant
|
102
|
+
end
|
103
|
+
variants
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def invalid_part?(part)
|
110
|
+
part.product
|
111
|
+
.product_properties
|
112
|
+
.where(property_id: default_property_id)
|
113
|
+
.present?
|
114
|
+
end
|
115
|
+
|
116
|
+
def default_property_id
|
117
|
+
::Spree::Property.find_by(
|
118
|
+
name: SolidusBactracs.config.default_property_name,
|
119
|
+
)&.id
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
module Api
|
5
5
|
class BatchSyncer
|
6
6
|
class << self
|
7
7
|
def from_config
|
8
8
|
new(
|
9
|
-
client:
|
10
|
-
shipment_matcher:
|
9
|
+
client: SolidusBactracs::Api::Client.from_config,
|
10
|
+
shipment_matcher: SolidusBactracs.config.api_shipment_matcher,
|
11
11
|
)
|
12
12
|
end
|
13
13
|
end
|
@@ -24,7 +24,7 @@ module SolidusBacktracs
|
|
24
24
|
response = client.bulk_create_orders(shipments)
|
25
25
|
rescue RateLimitedError => e
|
26
26
|
::Spree::Event.fire(
|
27
|
-
'
|
27
|
+
'solidus_bactracs.api.rate_limited',
|
28
28
|
shipments: shipments,
|
29
29
|
error: e,
|
30
30
|
)
|
@@ -32,7 +32,7 @@ module SolidusBacktracs
|
|
32
32
|
raise e
|
33
33
|
rescue RequestError => e
|
34
34
|
::Spree::Event.fire(
|
35
|
-
'
|
35
|
+
'solidus_bactracs.api.sync_errored',
|
36
36
|
shipments: shipments,
|
37
37
|
error: e,
|
38
38
|
)
|
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
module Api
|
5
5
|
class Client
|
6
6
|
class << self
|
7
7
|
def from_config
|
8
8
|
new(
|
9
9
|
request_runner: RequestRunner.new,
|
10
|
-
error_handler:
|
11
|
-
shipment_serializer:
|
10
|
+
error_handler: SolidusBactracs.config.error_handler,
|
11
|
+
shipment_serializer: SolidusBactracs.config.api_shipment_serializer,
|
12
12
|
)
|
13
13
|
end
|
14
14
|
end
|
@@ -23,7 +23,7 @@ module SolidusBacktracs
|
|
23
23
|
|
24
24
|
def bulk_create_orders(shipments)
|
25
25
|
shipments.each do |shipment|
|
26
|
-
|
26
|
+
SolidusBactracs::Api::SyncShipmentJob.perform_now(
|
27
27
|
shipment_id: shipment.id,
|
28
28
|
error_handler: @error_handler,
|
29
29
|
shipment_serializer: @shipment_serializer,
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "uri"
|
3
|
+
require "net/http"
|
4
|
+
|
5
|
+
module SolidusBactracs
|
6
|
+
module Api
|
7
|
+
class RequestRunner
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@username = SolidusBactracs.configuration.authentication_username
|
11
|
+
@password = SolidusBactracs.configuration.authentication_password
|
12
|
+
@api_base = SolidusBactracs.configuration.api_base
|
13
|
+
@retries = SolidusBactracs.configuration.api_retries
|
14
|
+
end
|
15
|
+
|
16
|
+
def authenticated_call(method: nil, path: nil, serializer: nil, shipment: nil, count: 0)
|
17
|
+
if count <= @retries
|
18
|
+
sguid = authenticate! rescue nil
|
19
|
+
|
20
|
+
if !sguid.presence
|
21
|
+
clear_cache
|
22
|
+
count += 1
|
23
|
+
self.authenticated_call(method: :post, path: '/webservices/rma/rmaservice.asmx', serializer: serializer, shipment: shipment, count: count)
|
24
|
+
else
|
25
|
+
params = serializer.call(shipment, sguid)
|
26
|
+
|
27
|
+
rma_response = call(method: :post, path: path, params: params)
|
28
|
+
if create_rma_success?(rma_response)
|
29
|
+
Rails.logger.info({ event: 'success CreateRMA', rma: shipment.number, response: parse_rma_creation_response(rma_response, "Message")})
|
30
|
+
shipment_synced(shipment)
|
31
|
+
return true
|
32
|
+
elsif rma_exists?(rma_response)
|
33
|
+
return false
|
34
|
+
else
|
35
|
+
clear_cache
|
36
|
+
count += 1
|
37
|
+
Rails.logger.warn({ event: 'bactracs failed CreateRMA', error: parse_rma_creation_response(rma_response, "Message")})
|
38
|
+
self.authenticated_call(method: :post, path: '/webservices/rma/rmaservice.asmx', serializer: serializer, shipment: shipment, count: count)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
shipment_sync_failed(shipment)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def call(method: nil, path: nil, params: {})
|
48
|
+
doc = {}
|
49
|
+
if params.present?
|
50
|
+
doc = Nokogiri::XML(params.to_s)
|
51
|
+
end
|
52
|
+
response = HTTParty.send(
|
53
|
+
method,
|
54
|
+
URI.join(@api_base, path),
|
55
|
+
body: doc.to_xml,
|
56
|
+
http_proxyaddr: SolidusBactracs.configuration.proxy_address,
|
57
|
+
http_proxyport: SolidusBactracs.configuration.proxy_port,
|
58
|
+
http_proxyuser: SolidusBactracs.configuration.proxy_username,
|
59
|
+
http_proxypass: SolidusBactracs.configuration.proxy_password,
|
60
|
+
headers: {
|
61
|
+
'Content-Type' => 'text/xml',
|
62
|
+
},
|
63
|
+
)
|
64
|
+
|
65
|
+
case response.code.to_s
|
66
|
+
when /2\d{2}/
|
67
|
+
response
|
68
|
+
when '429'
|
69
|
+
raise RateLimitedError.from_response(response)
|
70
|
+
else
|
71
|
+
raise RequestError.from_response(response)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def clear_cache
|
76
|
+
Rails.cache.delete('bactracks_cache_key')
|
77
|
+
@response = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def authenticate!()
|
81
|
+
unless @username.present? || @password.present? || @api_base.present?
|
82
|
+
raise "Credentials not defined for Authentication"
|
83
|
+
end
|
84
|
+
|
85
|
+
@response = Rails.cache.fetch("backtracks_cache_key", expires_in: 1.hour, skip_nil: true) do
|
86
|
+
self.call(method: :get, path: "/webservices/user/Authentication.asmx/Login?sUserName=#{@username}&sPassword=#{@password}")
|
87
|
+
end
|
88
|
+
|
89
|
+
raise RequestError.from_response(@response) unless @response # just try again for @retries?
|
90
|
+
if "false" == parse_authentication_response(@response, "Result")
|
91
|
+
Rails.logger.warn({ event: 'bactracs auth failed', error: parse_authentication_response(@response, "Message")})
|
92
|
+
raise RequestError.from_response(@response)
|
93
|
+
end
|
94
|
+
sguid = parse_authentication_response(@response, "Message")
|
95
|
+
|
96
|
+
return sguid
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_authentication_response(response, field)
|
100
|
+
response.dig("AuthenticationResponse", field)
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_rma_creation_response(response, field = "Result")
|
104
|
+
response.dig("Envelope", "Body", "CreateNewResponse", "CreateNewResult", field).to_s.downcase
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_rma_success?(response)
|
108
|
+
parse_rma_creation_response(response) == 'true' && parse_rma_creation_response(response, "Message") == "ok"
|
109
|
+
end
|
110
|
+
|
111
|
+
def rma_exists?(response)
|
112
|
+
if parse_rma_creation_response(response, "Message").match(/rma .* already exists/)
|
113
|
+
Rails.logger.warn({ event: 'bactracs failed CreateRMA', error: parse_rma_creation_response(rma_response, "Message")})
|
114
|
+
return true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def shipment_synced(shipment)
|
119
|
+
shipment.update_column(:bactracs_synced_at, Time.zone.now)
|
120
|
+
|
121
|
+
::Spree::Event.fire(
|
122
|
+
'solidus_bactracs.api.sync_completed',
|
123
|
+
shipment: shipment
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
def shipment_sync_failed(shipment)
|
128
|
+
::Spree::Event.fire(
|
129
|
+
'solidus_bactracs.api.sync_failed',
|
130
|
+
shipment: shipment
|
131
|
+
)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
module Api
|
5
5
|
class ShipmentSerializer
|
6
6
|
|
7
7
|
def initialize(shipment:)
|
8
8
|
@shipment = shipment
|
9
|
-
@config =
|
10
|
-
@property_id = ::Spree::Property.find_by(name:
|
9
|
+
@config = SolidusBactracs.config
|
10
|
+
@property_id = ::Spree::Property.find_by(name: SolidusBactracs.config.default_property_name)&.id
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(sguid: nil)
|
14
14
|
order = @shipment.order
|
15
15
|
user = @shipment.user
|
16
16
|
|
17
|
-
xml = Builder::XmlMarkup.new
|
17
|
+
xml = Builder::XmlMarkup.new
|
18
18
|
xml.instruct!(:xml, :encoding => "UTF-8")
|
19
19
|
|
20
20
|
xml.soap(:Envelope, {"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema", "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/"}) do
|
@@ -24,28 +24,28 @@ module SolidusBacktracs
|
|
24
24
|
xml.NewRMA {
|
25
25
|
xml.RMANumber @shipment.number
|
26
26
|
xml.RMATypeName @config.default_rma_type
|
27
|
-
xml.RMASubTypeName
|
28
|
-
xml.CustomerRef
|
29
|
-
xml.InboundShippingPriority
|
27
|
+
xml.RMASubTypeName
|
28
|
+
xml.CustomerRef
|
29
|
+
xml.InboundShippingPriority
|
30
30
|
xml.InboundTrackingNumber @shipment.tracking
|
31
31
|
|
32
32
|
xml.Ship {
|
33
33
|
xml.Carrier @config.default_carrier
|
34
34
|
xml.ShipMethod @config.default_ship_method
|
35
|
-
xml.ShipDate @shipment.created_at.strftime(
|
35
|
+
xml.ShipDate @shipment.created_at.strftime(SolidusBactracs::ExportHelper::BACTRACS_DATE_FORMAT)
|
36
36
|
xml.TrackingNumber @shipment.tracking
|
37
37
|
xml.SerialNumber @shipment.number
|
38
|
-
xml.Ud1
|
38
|
+
xml.Ud1
|
39
39
|
}
|
40
40
|
xml.Customer {
|
41
|
-
|
42
|
-
|
41
|
+
SolidusBactracs::ExportHelper.bactracs_address(xml, order, :ship)
|
42
|
+
SolidusBactracs::ExportHelper.bactracs_address(xml, order, :bill)
|
43
43
|
}
|
44
44
|
xml.Rep {
|
45
|
-
xml.Code
|
45
|
+
xml.Code
|
46
46
|
xml.Name user.full_name
|
47
47
|
xml.Email user.email
|
48
|
-
}
|
48
|
+
}
|
49
49
|
|
50
50
|
xml.RMALines {
|
51
51
|
@shipment.line_items.each do |line|
|
@@ -60,39 +60,40 @@ module SolidusBacktracs
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
}
|
63
|
-
xml.OrderDate order.completed_at.strftime(
|
64
|
-
xml.CreateDate @shipment.created_at.strftime(
|
63
|
+
xml.OrderDate order.completed_at.strftime(SolidusBactracs::ExportHelper::BACTRACS_DATE_FORMAT)
|
64
|
+
xml.CreateDate @shipment.created_at.strftime(SolidusBactracs::ExportHelper::BACTRACS_DATE_FORMAT)
|
65
65
|
xml.Status @config.default_status
|
66
66
|
xml.RMAId @shipment.id
|
67
67
|
xml.ClientGuid
|
68
68
|
}
|
69
69
|
end
|
70
|
-
end
|
70
|
+
end
|
71
71
|
end
|
72
|
+
Rails.logger.info(xml.to_s)
|
72
73
|
xml
|
73
74
|
end
|
74
75
|
|
75
76
|
def line_items_xml(xml: nil, line_item: nil, variant: nil, order: nil)
|
76
|
-
shipment_notice = @shipment.shipment_notice
|
77
|
+
shipment_notice = @shipment.shipment_notice
|
77
78
|
xml.RMALine {
|
78
79
|
xml.DFItem find_sku_variant(variant)
|
79
80
|
xml.DFModelNum find_sku_variant(variant)
|
80
|
-
xml.DFCategory
|
81
|
-
xml.DFCategoryDescription
|
81
|
+
xml.DFCategory
|
82
|
+
xml.DFCategoryDescription
|
82
83
|
xml.DFQuantity line_item.quantity
|
83
84
|
xml.DFUnitPrice line_item.price
|
84
|
-
xml.DFSerialNumbers
|
85
|
-
xml.Ud1s
|
86
|
-
xml.CurrentWarranties
|
87
|
-
xml.DFComments
|
85
|
+
xml.DFSerialNumbers
|
86
|
+
xml.Ud1s
|
87
|
+
xml.CurrentWarranties
|
88
|
+
xml.DFComments
|
88
89
|
xml.DFStatus @shipment.state
|
89
|
-
xml.PurchaseDate order.completed_at.strftime(
|
90
|
+
xml.PurchaseDate order.completed_at.strftime(SolidusBactracs::ExportHelper::BACTRACS_DATE_FORMAT)
|
90
91
|
xml.ServiceProvider shipment_notice&.service
|
91
|
-
xml.WarrantyRepair
|
92
|
-
xml.RMALineTest
|
92
|
+
xml.WarrantyRepair
|
93
|
+
xml.RMALineTest
|
93
94
|
xml.InboundShipWeight variant.weight.to_f
|
94
95
|
xml.RPLocation @config.default_rp_location
|
95
|
-
}
|
96
|
+
}
|
96
97
|
end
|
97
98
|
|
98
99
|
def find_sku_variant(variant)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
module Api
|
5
5
|
class ThresholdVerifier
|
6
6
|
class << self
|
@@ -13,14 +13,14 @@ module SolidusBacktracs
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def shipment_requires_creation?(shipment)
|
16
|
-
shipment.
|
17
|
-
Time.zone.now - shipment.order.updated_at <
|
16
|
+
shipment.bactracs_synced_at.nil? &&
|
17
|
+
Time.zone.now - shipment.order.updated_at < SolidusBactracs.config.api_sync_threshold
|
18
18
|
end
|
19
19
|
|
20
20
|
def shipment_requires_update?(shipment)
|
21
|
-
shipment.
|
22
|
-
shipment.
|
23
|
-
Time.zone.now - shipment.order.updated_at <
|
21
|
+
shipment.bactracs_synced_at &&
|
22
|
+
shipment.bactracs_synced_at < shipment.order.updated_at &&
|
23
|
+
Time.zone.now - shipment.order.updated_at < SolidusBactracs.config.api_sync_threshold
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
class Configuration
|
5
5
|
attr_accessor(
|
6
6
|
:webhook_username,
|
@@ -41,11 +41,11 @@ module SolidusBacktracs
|
|
41
41
|
@error_handler = ->(_error, _extra = {}) {
|
42
42
|
Rails.logger.error "#{error.inspect} (#{extra.inspect})"
|
43
43
|
}
|
44
|
-
@api_shipment_matcher = proc do |
|
45
|
-
shipments.find { |shipment| shipment.number ==
|
44
|
+
@api_shipment_matcher = proc do |bactracs_order, shipments|
|
45
|
+
shipments.find { |shipment| shipment.number == bactracs_order['orderNumber'] }
|
46
46
|
end
|
47
47
|
|
48
|
-
@shipment_notice_class = '
|
48
|
+
@shipment_notice_class = 'SolidusBactracs::ShipmentNotice'
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -3,13 +3,13 @@
|
|
3
3
|
require 'solidus_core'
|
4
4
|
require 'solidus_support'
|
5
5
|
|
6
|
-
module
|
6
|
+
module SolidusBactracs
|
7
7
|
class Engine < Rails::Engine
|
8
8
|
include SolidusSupport::EngineExtensions
|
9
9
|
|
10
10
|
isolate_namespace ::Spree
|
11
11
|
|
12
|
-
engine_name '
|
12
|
+
engine_name 'solidus_bactracs'
|
13
13
|
|
14
14
|
# use rspec for tests
|
15
15
|
config.generators do |g|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module SolidusBactracs
|
4
4
|
class ShipmentNotice
|
5
5
|
attr_reader :shipment_number, :shipment_tracking
|
6
6
|
|
@@ -38,7 +38,7 @@ module SolidusBacktracs
|
|
38
38
|
def process_payment
|
39
39
|
return if shipment.order.paid?
|
40
40
|
|
41
|
-
unless
|
41
|
+
unless SolidusBactracs.configuration.capture_at_notification
|
42
42
|
raise OrderNotPaidError, shipment.order
|
43
43
|
end
|
44
44
|
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
require 'solidus_bactracs/api/batch_syncer'
|
6
|
+
require 'solidus_bactracs/api/request_runner'
|
7
|
+
require 'solidus_bactracs/api/client'
|
8
|
+
require 'solidus_bactracs/api/request_error'
|
9
|
+
require 'solidus_bactracs/api/rate_limited_error'
|
10
|
+
require 'solidus_bactracs/api/shipment_serializer'
|
11
|
+
require 'solidus_bactracs/api/threshold_verifier'
|
12
|
+
require 'solidus_bactracs/configuration'
|
13
|
+
require 'solidus_bactracs/errors'
|
14
|
+
require 'solidus_bactracs/shipment_notice'
|
15
|
+
require 'solidus_bactracs/version'
|
16
|
+
require 'solidus_bactracs/engine'
|
data/solidus_bactracs.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'lib/
|
3
|
+
require_relative 'lib/solidus_bactracs/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'solidus_bactracs'
|
7
|
-
spec.version =
|
7
|
+
spec.version = SolidusBactracs::VERSION
|
8
8
|
spec.authors = ['Zeryab Ali', 'Zachary Jones']
|
9
9
|
spec.email = 'techbilling@suvie.com'
|
10
10
|
|
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.metadata['homepage_uri'] = spec.homepage
|
16
16
|
spec.metadata['source_code_uri'] = 'https://github.com/suvie-eng/solidus_bactracs/'
|
17
17
|
spec.metadata['changelog_uri'] = 'https://github.com/suvie-eng/solidus_bactracs/blob/master/CHANGELOG.md'
|
18
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
18
19
|
|
19
20
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.5')
|
20
21
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
RSpec.describe Spree::
|
3
|
+
RSpec.describe Spree::BactracsController do
|
4
4
|
render_views
|
5
5
|
|
6
6
|
describe '#export' do
|
@@ -14,7 +14,7 @@ RSpec.describe Spree::BacktracsController do
|
|
14
14
|
|
15
15
|
context 'when the authentication is valid' do
|
16
16
|
it 'responds with 200 OK' do
|
17
|
-
|
17
|
+
stub_bactracs_auth
|
18
18
|
create(:order_ready_to_ship)
|
19
19
|
|
20
20
|
get :export,
|
@@ -27,8 +27,8 @@ RSpec.describe Spree::BacktracsController do
|
|
27
27
|
expect(response.status).to eq(200)
|
28
28
|
end
|
29
29
|
|
30
|
-
it 'generates
|
31
|
-
|
30
|
+
it 'generates Bactracs-compliant XML' do
|
31
|
+
stub_bactracs_auth
|
32
32
|
create(:order_ready_to_ship)
|
33
33
|
|
34
34
|
get :export, params: {
|
@@ -37,7 +37,7 @@ RSpec.describe Spree::BacktracsController do
|
|
37
37
|
format: 'xml'
|
38
38
|
}
|
39
39
|
|
40
|
-
expect(response.body).to pass_validation('spec/fixtures/
|
40
|
+
expect(response.body).to pass_validation('spec/fixtures/bactracs_xml_schema.xsd')
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -46,7 +46,7 @@ RSpec.describe Spree::BacktracsController do
|
|
46
46
|
context 'when the authentication is valid' do
|
47
47
|
context 'when the shipment can be found' do
|
48
48
|
it 'responds with 200 OK' do
|
49
|
-
|
49
|
+
stub_bactracs_auth
|
50
50
|
shipment = create(:order_ready_to_ship).shipments.first
|
51
51
|
|
52
52
|
post :shipnotify, params: {
|
@@ -60,7 +60,7 @@ RSpec.describe Spree::BacktracsController do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'updates the shipment' do
|
63
|
-
|
63
|
+
stub_bactracs_auth
|
64
64
|
shipment = create(:order_ready_to_ship).shipments.first
|
65
65
|
|
66
66
|
post :shipnotify, params: {
|
@@ -80,7 +80,7 @@ RSpec.describe Spree::BacktracsController do
|
|
80
80
|
|
81
81
|
context 'when the shipment cannot be found' do
|
82
82
|
it 'responds with 400 Bad Request' do
|
83
|
-
|
83
|
+
stub_bactracs_auth
|
84
84
|
shipment = create(:order_ready_to_ship).shipments.first
|
85
85
|
|
86
86
|
post :shipnotify, params: {
|
@@ -96,7 +96,7 @@ RSpec.describe Spree::BacktracsController do
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
def
|
99
|
+
def stub_bactracs_auth(username = 'mario', password = 'lemieux')
|
100
100
|
stub_configuration(username: username, password: password)
|
101
101
|
request.headers['Authorization'] = ActionController::HttpAuthentication::Basic.encode_credentials(username, password)
|
102
102
|
end
|
File without changes
|