flowcommerce_spree 0.0.1 → 0.0.6
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 +4 -4
- data/README.md +101 -24
- data/SPREE_FLOW.md +6 -28
- data/app/controllers/concerns/current_zone_loader_decorator.rb +40 -25
- data/app/controllers/flowcommerce_spree/inventory_controller.rb +23 -0
- data/app/controllers/flowcommerce_spree/orders_controller.rb +20 -0
- data/app/controllers/flowcommerce_spree/webhooks_controller.rb +23 -13
- data/app/controllers/users/sessions_controller_decorator.rb +28 -0
- data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +4 -9
- data/app/models/spree/address_decorator.rb +19 -0
- data/app/models/spree/app_configuration_decorator.rb +7 -0
- data/app/models/spree/calculator/flow_io.rb +61 -0
- data/app/models/spree/calculator/shipping/flow_io.rb +40 -0
- data/app/models/spree/flow_io_credit_card_decorator.rb +21 -0
- data/app/models/spree/flow_io_order_decorator.rb +163 -0
- data/app/models/spree/flow_io_product_decorator.rb +2 -2
- data/app/models/spree/flow_io_variant_decorator.rb +4 -2
- data/app/models/spree/gateway/flow_io.rb +153 -0
- data/app/models/spree/{credit_card_decorator.rb → payment_capture_event_decorator.rb} +1 -1
- data/app/models/spree/promotion_handler/coupon_decorator.rb +1 -1
- data/app/models/spree/zones/flow_io_product_zone_decorator.rb +8 -0
- data/app/models/tracking/setup_decorator.rb +40 -0
- data/app/overrides/spree/admin/order_sidebar_summary_flow_link.rb +13 -0
- data/app/overrides/spree/admin/products/order_price_flow_message.rb +9 -0
- data/app/serializers/api/v2/order_serializer_decorator.rb +20 -0
- data/app/services/flowcommerce_spree/import_experience_items.rb +1 -1
- data/app/services/flowcommerce_spree/order_sync.rb +81 -173
- data/app/services/flowcommerce_spree/order_updater.rb +78 -0
- data/app/services/flowcommerce_spree/webhooks/capture_upserted_v2.rb +76 -0
- data/app/services/flowcommerce_spree/webhooks/card_authorization_upserted_v2.rb +66 -0
- data/app/services/flowcommerce_spree/webhooks/experience_upserted_v2.rb +25 -0
- data/app/services/flowcommerce_spree/webhooks/fraud_status_changed.rb +35 -0
- data/app/services/flowcommerce_spree/webhooks/local_item_upserted.rb +40 -0
- data/app/views/spree/admin/payments/source_views/_flow_io_gateway.html.erb +21 -0
- data/config/rails_best_practices.yml +51 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +6 -4
- data/lib/flow/simple_gateway.rb +0 -36
- data/lib/flowcommerce_spree.rb +17 -3
- data/lib/flowcommerce_spree/engine.rb +33 -3
- data/lib/flowcommerce_spree/experience_service.rb +1 -27
- data/lib/flowcommerce_spree/logging_http_client.rb +33 -15
- data/lib/flowcommerce_spree/session.rb +16 -29
- data/lib/flowcommerce_spree/test_support.rb +7 -0
- data/lib/flowcommerce_spree/version.rb +1 -1
- data/lib/tasks/flowcommerce_spree.rake +4 -1
- metadata +90 -22
- data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
- data/app/models/spree/gateway/spree_flow_gateway.rb +0 -116
- data/app/models/spree/line_item_decorator.rb +0 -15
- data/app/models/spree/order_decorator.rb +0 -179
- data/app/views/spree/order_mailer/confirm_email.html.erb +0 -86
- data/app/views/spree/order_mailer/confirm_email.text.erb +0 -38
- data/config/initializers/flowcommerce_spree.rb +0 -7
- data/lib/flow/error.rb +0 -73
- data/lib/flow/pay_pal.rb +0 -25
- data/lib/flowcommerce_spree/webhook_service.rb +0 -98
- data/lib/simple_csv_writer.rb +0 -44
data/lib/flow/error.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Flow (2017)
|
4
|
-
# api error logger and formater
|
5
|
-
|
6
|
-
require 'digest/sha1'
|
7
|
-
|
8
|
-
class Flow::Error < StandardError
|
9
|
-
# logs error to file for easy discovery and fix
|
10
|
-
def self.log(exception, request)
|
11
|
-
history = exception.backtrace.reject { |el| el.index('/gems/') }.map { |el| el.sub(Rails.root.to_s, '') }.join($/)
|
12
|
-
|
13
|
-
msg = "#{exception.class} in #{request.url}"
|
14
|
-
data = [msg, exception.message, history].join("\n\n")
|
15
|
-
key = Digest::SHA1.hexdigest(exception.backtrace.first.split(' ').first)
|
16
|
-
|
17
|
-
folder = Rails.root.join('log/exceptions').to_s
|
18
|
-
Dir.mkdir(folder) unless Dir.exist?(folder)
|
19
|
-
|
20
|
-
folder += "/#{exception.class.to_s.tableize.gsub('/', '-')}"
|
21
|
-
Dir.mkdir(folder) unless Dir.exist?(folder)
|
22
|
-
|
23
|
-
"#{folder}/#{key}.txt".tap do |path|
|
24
|
-
File.write(path, data)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.format_message(exception)
|
29
|
-
# format Flow errors in a special way
|
30
|
-
# Io::Flow::V0::HttpClient::ServerError - 422 Unprocessable Entity:
|
31
|
-
# {"code":"invalid_number","messages":["Card number is not valid"]}
|
32
|
-
# hash['code'] = 'invalid_number'
|
33
|
-
# hash['message'] = 'Card number is not valid'
|
34
|
-
# hash['title'] = '422 Unprocessable Entity'
|
35
|
-
# hash['klass'] = 'Io::Flow::V0::HttpClient::ServerError'
|
36
|
-
if exception.class == Io::Flow::V0::HttpClient::ServerError
|
37
|
-
parts = exception.message.split(': ', 2)
|
38
|
-
hash = Oj.load(parts[1])
|
39
|
-
|
40
|
-
hash[:message] = hash['messages'].join(', ')
|
41
|
-
hash[:title] = parts[0]
|
42
|
-
hash[:klass] = exception.class
|
43
|
-
hash[:code] = hash['code']
|
44
|
-
else
|
45
|
-
msg = exception.message.is_a?(Array) ? exception.message.join(' - ') : exception.message
|
46
|
-
|
47
|
-
hash = {}
|
48
|
-
hash[:message] = msg
|
49
|
-
hash[:title] = '-'
|
50
|
-
hash[:klass] = exception.class
|
51
|
-
hash[:code] = '-'
|
52
|
-
end
|
53
|
-
|
54
|
-
hash
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.format_order_message(order)
|
58
|
-
message = if order['messages']
|
59
|
-
msg = order['messages'].join(', ')
|
60
|
-
msg += " (#{Spree::Variant.where(id: order['numbers']).map(&:name).join(', ')})" if order['numbers']
|
61
|
-
msg
|
62
|
-
else
|
63
|
-
'Order not properly localized (sync issue)'
|
64
|
-
end
|
65
|
-
|
66
|
-
# sub_info = 'Flow.io'
|
67
|
-
# sub_info += ' - %s' % flow_experience.key[0, 15] if flow_experience
|
68
|
-
|
69
|
-
# '%s (%s)' % [message, sub_info]
|
70
|
-
|
71
|
-
message
|
72
|
-
end
|
73
|
-
end
|
data/lib/flow/pay_pal.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Flow.io (2017)
|
4
|
-
# communicates with flow api to synchronize Spree order with PayPal
|
5
|
-
|
6
|
-
module Flow::PayPal
|
7
|
-
extend self
|
8
|
-
|
9
|
-
def get_id(order)
|
10
|
-
raise 'PayPal only supported while using flow' unless order.flow_order
|
11
|
-
|
12
|
-
# get PayPal ID using Flow api
|
13
|
-
body = {
|
14
|
-
# discriminator: 'merchant_of_record_payment_form',
|
15
|
-
method: 'paypal',
|
16
|
-
order_number: order.number,
|
17
|
-
amount: order.flow_order.total.amount,
|
18
|
-
currency: order.flow_order.total.currency
|
19
|
-
}
|
20
|
-
|
21
|
-
# FlowcommerceSpree::Api.run :post, '/:organization/payments', {}, body
|
22
|
-
form = ::Io::Flow::V0::Models::MerchantOfRecordPaymentForm.new body
|
23
|
-
FlowcommerceSpree.client.payments.post FlowcommerceSpree::ORGANIZATION, form
|
24
|
-
end
|
25
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FlowcommerceSpree
|
4
|
-
# communicates with flow api, responds to webhook events
|
5
|
-
class WebhookService
|
6
|
-
attr_accessor :errors, :product, :variant
|
7
|
-
alias full_messages errors
|
8
|
-
|
9
|
-
def self.process(data, opts = {})
|
10
|
-
new(data, opts).process
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(data, opts = {})
|
14
|
-
@data = data
|
15
|
-
@opts = opts
|
16
|
-
@errors = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def process
|
20
|
-
org = @data['organization']
|
21
|
-
if org != ORGANIZATION
|
22
|
-
errors << { message: "Organization name mismatch for #{org}" }
|
23
|
-
else
|
24
|
-
discriminator = @data['discriminator']
|
25
|
-
hook_method = "hook_#{discriminator}"
|
26
|
-
# If hook processing method registered an error, a self.object of WebhookService with this error will be
|
27
|
-
# returned, else an ActiveRecord object will be returned
|
28
|
-
return __send__(hook_method) if respond_to?(hook_method, true)
|
29
|
-
|
30
|
-
errors << { message: "No hook for #{discriminator}" }
|
31
|
-
end
|
32
|
-
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def hook_experience_upserted_v2
|
39
|
-
experience = @data['experience']
|
40
|
-
Spree::Zones::Product.find_or_initialize_by(name: experience['key'].titleize).store_flow_io_data(experience)
|
41
|
-
end
|
42
|
-
|
43
|
-
def hook_local_item_upserted
|
44
|
-
if (local_item = @data['local_item'])
|
45
|
-
if (received_sku = local_item.dig('item', 'number'))
|
46
|
-
if (@variant = Spree::Variant.find_by(sku: received_sku))
|
47
|
-
@variant.add_flow_io_experience_data(
|
48
|
-
local_item.dig('experience', 'key'),
|
49
|
-
'prices' => [local_item.dig('pricing', 'price')], 'status' => local_item['status']
|
50
|
-
)
|
51
|
-
|
52
|
-
@variant.update_column(:meta, @variant.meta.to_json)
|
53
|
-
return @variant
|
54
|
-
else
|
55
|
-
errors << { message: "Variant with sku [#{received_sku}] not found!" }
|
56
|
-
end
|
57
|
-
else
|
58
|
-
errors << { message: 'SKU param missing' }
|
59
|
-
end
|
60
|
-
else
|
61
|
-
errors << { message: 'Local item param missing' }
|
62
|
-
end
|
63
|
-
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
def hook_order_upserted_v2
|
68
|
-
errors << { message: 'Order param missing' } unless (received_order = @data['order'])
|
69
|
-
|
70
|
-
if errors.none? && (order_number = received_order['number'])
|
71
|
-
if (order = Spree::Order.find_by(number: order_number))
|
72
|
-
order.flow_data['order'] = received_order.to_hash
|
73
|
-
attrs_to_update = { meta: order.meta.to_json }
|
74
|
-
if order.flow_data['order']['submitted_at'].present?
|
75
|
-
attrs_to_update[:state] = 'complete'
|
76
|
-
attrs_to_update[:completed_at] = Time.zone.now
|
77
|
-
end
|
78
|
-
|
79
|
-
order.update_columns(attrs_to_update)
|
80
|
-
return order
|
81
|
-
else
|
82
|
-
errors << { message: "Order #{order_number} not found" }
|
83
|
-
end
|
84
|
-
else
|
85
|
-
errors << { message: 'Order number param missing' }
|
86
|
-
end
|
87
|
-
|
88
|
-
self
|
89
|
-
end
|
90
|
-
|
91
|
-
# send en email when order is refunded
|
92
|
-
def hook_refund_upserted_v2
|
93
|
-
Spree::OrderMailer.refund_complete_email(@data).deliver
|
94
|
-
|
95
|
-
'Email delivered'
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
data/lib/simple_csv_writer.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# simple class to build scv files
|
4
|
-
|
5
|
-
# csv = CsvWriter.new
|
6
|
-
# csv.add a: 1, b: 'a', c: '"a'
|
7
|
-
# csv.add a: ',', b: 'foo, bar'
|
8
|
-
# csv.to_s
|
9
|
-
|
10
|
-
class SimpleCsvWriter
|
11
|
-
def initialize(delimiter: nil)
|
12
|
-
@data = []
|
13
|
-
@delimiter = delimiter || "\t"
|
14
|
-
end
|
15
|
-
|
16
|
-
# add hash or list
|
17
|
-
def add(data)
|
18
|
-
list = if data.class == Hash
|
19
|
-
@keys ||= data.keys
|
20
|
-
@keys.map { |key| data[key] }
|
21
|
-
else
|
22
|
-
data
|
23
|
-
end
|
24
|
-
|
25
|
-
@data.push list.map { |el| fmt(el) }.join(@delimiter)
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_s
|
29
|
-
if @keys
|
30
|
-
@keys.map(&:to_s).join(@delimiter) + "\n" +
|
31
|
-
@data.join($RS)
|
32
|
-
else
|
33
|
-
@data.join($RS)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def fmt(item)
|
40
|
-
item = item.to_s.gsub($RS, '\\n').gsub('"', '""')
|
41
|
-
|
42
|
-
item.include?(@delimiter) || item.include?('\\') ? "\"#{item}\"" : item
|
43
|
-
end
|
44
|
-
end
|