flowcommerce_spree 0.0.3 → 0.0.8

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -6
  3. data/app/controllers/concerns/current_zone_loader_decorator.rb +11 -17
  4. data/app/controllers/flowcommerce_spree/inventory_controller.rb +23 -0
  5. data/app/controllers/flowcommerce_spree/orders_controller.rb +20 -0
  6. data/app/controllers/flowcommerce_spree/webhooks_controller.rb +16 -18
  7. data/app/controllers/users/sessions_controller_decorator.rb +19 -2
  8. data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +0 -16
  9. data/app/models/flowcommerce_spree/settings.rb +1 -0
  10. data/app/models/spree/address_decorator.rb +1 -1
  11. data/app/models/spree/calculator/flow_io.rb +24 -12
  12. data/app/models/spree/calculator/shipping/flow_io.rb +5 -2
  13. data/app/models/spree/flow_io_credit_card_decorator.rb +21 -0
  14. data/app/models/spree/flow_io_order_decorator.rb +181 -0
  15. data/app/models/spree/flow_io_product_decorator.rb +5 -0
  16. data/app/models/spree/flow_io_variant_decorator.rb +16 -6
  17. data/app/models/spree/gateway/flow_io.rb +61 -24
  18. data/app/models/spree/{credit_card_decorator.rb → payment_capture_event_decorator.rb} +1 -1
  19. data/app/models/spree/zones/flow_io_product_zone_decorator.rb +4 -0
  20. data/app/overrides/spree/admin/order_sidebar_summary_flow_link.rb +13 -0
  21. data/app/overrides/spree/admin/products/order_price_flow_message.rb +9 -0
  22. data/app/serializers/api/v2/order_serializer_decorator.rb +20 -0
  23. data/app/services/flowcommerce_spree/import_experience_items.rb +1 -21
  24. data/app/services/flowcommerce_spree/import_item.rb +45 -0
  25. data/app/services/flowcommerce_spree/order_sync.rb +50 -222
  26. data/app/services/flowcommerce_spree/order_updater.rb +78 -0
  27. data/app/services/flowcommerce_spree/webhooks/capture_upserted_v2.rb +76 -0
  28. data/app/services/flowcommerce_spree/webhooks/card_authorization_upserted_v2.rb +66 -0
  29. data/app/services/flowcommerce_spree/webhooks/experience_upserted_v2.rb +25 -0
  30. data/app/services/flowcommerce_spree/webhooks/fraud_status_changed.rb +35 -0
  31. data/app/services/flowcommerce_spree/webhooks/local_item_upserted.rb +40 -0
  32. data/app/views/spree/admin/payments/source_views/_flow_io_gateway.html.erb +21 -0
  33. data/app/workers/flowcommerce_spree/import_item_worker.rb +24 -0
  34. data/config/routes.rb +3 -1
  35. data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +6 -4
  36. data/lib/flow/simple_gateway.rb +0 -36
  37. data/lib/flowcommerce_spree.rb +6 -2
  38. data/lib/flowcommerce_spree/engine.rb +6 -1
  39. data/lib/flowcommerce_spree/experience_service.rb +1 -27
  40. data/lib/flowcommerce_spree/logging_http_client.rb +29 -13
  41. data/lib/flowcommerce_spree/session.rb +5 -25
  42. data/lib/flowcommerce_spree/version.rb +1 -1
  43. data/lib/tasks/flowcommerce_spree.rake +4 -1
  44. metadata +77 -28
  45. data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
  46. data/app/models/spree/line_item_decorator.rb +0 -15
  47. data/app/models/spree/order_decorator.rb +0 -244
  48. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -86
  49. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -38
  50. data/lib/flow/error.rb +0 -73
  51. data/lib/flow/pay_pal.rb +0 -25
  52. data/lib/flowcommerce_spree/webhook_service.rb +0 -184
  53. data/lib/simple_csv_writer.rb +0 -44
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,184 +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
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
- discriminator = @data['discriminator']
21
- hook_method = "hook_#{discriminator}"
22
- # If hook processing method registered an error, a self.object of WebhookService with this error will be
23
- # returned, else an ActiveRecord object will be returned
24
- return __send__(hook_method) if respond_to?(hook_method, true)
25
-
26
- errors << { message: "No hook for #{discriminator}" }
27
- self
28
- end
29
-
30
- private
31
-
32
- def hook_capture_upserted_v2
33
- capture = @data['capture']
34
- order_number = capture.dig('authorization', 'order', 'number')
35
- if (order = Spree::Order.find_by(number: order_number))
36
- order.flow_data['captures'] ||= []
37
- order_captures = order.flow_data['captures']
38
- order_captures.delete_if do |c|
39
- c['id'] == capture['id']
40
- end
41
- order_captures << capture
42
-
43
- order.update_column(:meta, order.meta.to_json)
44
- order
45
- else
46
- errors << { message: "Order #{order_number} not found" }
47
- self
48
- end
49
- end
50
-
51
- def hook_experience_upserted_v2
52
- experience = @data['experience']
53
- Spree::Zones::Product.find_or_initialize_by(name: experience['key'].titleize).store_flow_io_data(experience)
54
- end
55
-
56
- def hook_fraud_status_changed
57
- if (order_number = @data.dig('order', 'number'))
58
- if @data['status'] == 'declined'
59
- if (order = Spree::Order.find_by(number: order_number))
60
- order.update_columns(fraudulent: true)
61
- order.cancel!
62
- return order
63
- else
64
- errors << { message: "Order #{order_number} not found" }
65
- end
66
- end
67
- else
68
- errors << { message: 'Order number param missing' }
69
- end
70
-
71
- self
72
- end
73
-
74
- def hook_local_item_upserted
75
- errors << { message: 'Local item param missing' } && (return self) unless (local_item = @data['local_item'])
76
-
77
- errors << { message: 'SKU param missing' } && (return self) unless (flow_sku = local_item.dig('item', 'number'))
78
-
79
- if (variant = Spree::Variant.find_by(sku: flow_sku))
80
- variant.add_flow_io_experience_data(
81
- local_item.dig('experience', 'key'),
82
- 'prices' => [local_item.dig('pricing', 'price')], 'status' => local_item['status']
83
- )
84
-
85
- variant.update_column(:meta, variant.meta.to_json)
86
- return variant
87
- else
88
- errors << { message: "Variant with sku [#{flow_sku}] not found!" }
89
- end
90
-
91
- self
92
- end
93
-
94
- def hook_order_placed_v2
95
- order_placed = @data['order_placed']
96
- flow_order = order_placed['order']
97
- flow_allocation = order_placed['allocation']
98
-
99
- errors << { message: 'Order number param missing' } && (return self) unless (order_number = flow_order['number'])
100
-
101
- if (order = Spree::Order.find_by(number: order_number))
102
- order.flow_data['order'] = flow_order.to_hash
103
- order.flow_data['allocations'] = flow_allocation.to_hash
104
- order_flow_data = order.flow_data['order']
105
- attrs_to_update = { meta: order.meta.to_json }
106
- flow_data_submitted = order_flow_data['submitted_at'].present?
107
- if flow_data_submitted && !order.complete?
108
- if order_flow_data['payments'].present? && (order_flow_data.dig('balance', 'amount')&.to_i == 0)
109
- attrs_to_update[:state] = 'complete'
110
- attrs_to_update[:payment_state] = 'paid'
111
- attrs_to_update[:completed_at] = Time.zone.now.utc
112
- attrs_to_update[:email] = order.flow_customer_email
113
- else
114
- attrs_to_update[:state] = 'confirmed'
115
- end
116
- end
117
-
118
- attrs_to_update.merge!(order.prepare_flow_addresses) if order.complete? || attrs_to_update[:state] == 'complete'
119
-
120
- if flow_data_submitted
121
- order.create_proposed_shipments
122
- order.shipment.update_amounts
123
- order.line_items.each(&:store_ets)
124
- end
125
-
126
- order.update_columns(attrs_to_update)
127
-
128
- # TODO: To be refactored once we have the capture_upserted_v2 webhook configured
129
- if flow_data_submitted
130
- order.create_tax_charge!
131
- order.finalize!
132
- order.update_totals
133
- order.save
134
- end
135
-
136
- return order
137
- else
138
- errors << { message: "Order #{order_number} not found" }
139
- end
140
-
141
- self
142
- end
143
-
144
- def hook_order_upserted_v2
145
- errors << { message: 'Order param missing' } && (return self) unless (flow_order = @data['order'])
146
-
147
- errors << { message: 'Order number param missing' } && (return self) unless (order_number = flow_order['number'])
148
-
149
- if (order = Spree::Order.find_by(number: order_number))
150
- order.flow_data['order'] = flow_order.to_hash
151
- order_flow_data = order.flow_data['order']
152
- attrs_to_update = { meta: order.meta.to_json }
153
- flow_data_submitted = order_flow_data['submitted_at'].present?
154
- if flow_data_submitted && !order.complete?
155
- if order_flow_data['payments'].present? && (order_flow_data.dig('balance', 'amount')&.to_i == 0)
156
- attrs_to_update[:state] = 'complete'
157
- attrs_to_update[:payment_state] = 'paid'
158
- attrs_to_update[:completed_at] = Time.zone.now.utc
159
- attrs_to_update[:email] = order.flow_customer_email
160
- else
161
- attrs_to_update[:state] = 'confirmed'
162
- end
163
- end
164
-
165
- attrs_to_update.merge!(order.prepare_flow_addresses) if order.complete? || attrs_to_update[:state] == 'complete'
166
-
167
- order.update_columns(attrs_to_update)
168
- order.create_tax_charge! if flow_data_submitted
169
- return order
170
- else
171
- errors << { message: "Order #{order_number} not found" }
172
- end
173
-
174
- self
175
- end
176
-
177
- # send en email when order is refunded
178
- def hook_refund_upserted_v2
179
- Spree::OrderMailer.refund_complete_email(@data).deliver
180
-
181
- 'Email delivered'
182
- end
183
- end
184
- 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