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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -24
  3. data/SPREE_FLOW.md +6 -28
  4. data/app/controllers/concerns/current_zone_loader_decorator.rb +40 -25
  5. data/app/controllers/flowcommerce_spree/inventory_controller.rb +23 -0
  6. data/app/controllers/flowcommerce_spree/orders_controller.rb +20 -0
  7. data/app/controllers/flowcommerce_spree/webhooks_controller.rb +23 -13
  8. data/app/controllers/users/sessions_controller_decorator.rb +28 -0
  9. data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +4 -9
  10. data/app/models/spree/address_decorator.rb +19 -0
  11. data/app/models/spree/app_configuration_decorator.rb +7 -0
  12. data/app/models/spree/calculator/flow_io.rb +61 -0
  13. data/app/models/spree/calculator/shipping/flow_io.rb +40 -0
  14. data/app/models/spree/flow_io_credit_card_decorator.rb +21 -0
  15. data/app/models/spree/flow_io_order_decorator.rb +163 -0
  16. data/app/models/spree/flow_io_product_decorator.rb +2 -2
  17. data/app/models/spree/flow_io_variant_decorator.rb +4 -2
  18. data/app/models/spree/gateway/flow_io.rb +153 -0
  19. data/app/models/spree/{credit_card_decorator.rb → payment_capture_event_decorator.rb} +1 -1
  20. data/app/models/spree/promotion_handler/coupon_decorator.rb +1 -1
  21. data/app/models/spree/zones/flow_io_product_zone_decorator.rb +8 -0
  22. data/app/models/tracking/setup_decorator.rb +40 -0
  23. data/app/overrides/spree/admin/order_sidebar_summary_flow_link.rb +13 -0
  24. data/app/overrides/spree/admin/products/order_price_flow_message.rb +9 -0
  25. data/app/serializers/api/v2/order_serializer_decorator.rb +20 -0
  26. data/app/services/flowcommerce_spree/import_experience_items.rb +1 -1
  27. data/app/services/flowcommerce_spree/order_sync.rb +81 -173
  28. data/app/services/flowcommerce_spree/order_updater.rb +78 -0
  29. data/app/services/flowcommerce_spree/webhooks/capture_upserted_v2.rb +76 -0
  30. data/app/services/flowcommerce_spree/webhooks/card_authorization_upserted_v2.rb +66 -0
  31. data/app/services/flowcommerce_spree/webhooks/experience_upserted_v2.rb +25 -0
  32. data/app/services/flowcommerce_spree/webhooks/fraud_status_changed.rb +35 -0
  33. data/app/services/flowcommerce_spree/webhooks/local_item_upserted.rb +40 -0
  34. data/app/views/spree/admin/payments/source_views/_flow_io_gateway.html.erb +21 -0
  35. data/config/rails_best_practices.yml +51 -0
  36. data/config/routes.rb +3 -1
  37. data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +6 -4
  38. data/lib/flow/simple_gateway.rb +0 -36
  39. data/lib/flowcommerce_spree.rb +17 -3
  40. data/lib/flowcommerce_spree/engine.rb +33 -3
  41. data/lib/flowcommerce_spree/experience_service.rb +1 -27
  42. data/lib/flowcommerce_spree/logging_http_client.rb +33 -15
  43. data/lib/flowcommerce_spree/session.rb +16 -29
  44. data/lib/flowcommerce_spree/test_support.rb +7 -0
  45. data/lib/flowcommerce_spree/version.rb +1 -1
  46. data/lib/tasks/flowcommerce_spree.rake +4 -1
  47. metadata +90 -22
  48. data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
  49. data/app/models/spree/gateway/spree_flow_gateway.rb +0 -116
  50. data/app/models/spree/line_item_decorator.rb +0 -15
  51. data/app/models/spree/order_decorator.rb +0 -179
  52. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -86
  53. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -38
  54. data/config/initializers/flowcommerce_spree.rb +0 -7
  55. data/lib/flow/error.rb +0 -73
  56. data/lib/flow/pay_pal.rb +0 -25
  57. data/lib/flowcommerce_spree/webhook_service.rb +0 -98
  58. data/lib/simple_csv_writer.rb +0 -44
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FlowcommerceSpree
4
- ORGANIZATION = ENV.fetch('FLOW_ORGANIZATION', 'flow.io')
5
- BASE_COUNTRY = ENV.fetch('FLOW_BASE_COUNTRY', 'USA')
6
- API_KEY = ENV.fetch('FLOW_TOKEN', 'test_key')
7
- end
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
@@ -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