flowcommerce_spree 0.0.2 → 0.0.7
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 +46 -13
- data/SPREE_FLOW.md +6 -28
- data/app/controllers/concerns/current_zone_loader_decorator.rb +33 -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/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_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 +17 -32
- 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 +88 -21
- 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
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Flow (2017)
|
4
|
-
# Enable this modifications if you want to display flow localized line item
|
5
|
-
# Example: https://i.imgur.com/7v2ix2G.png
|
6
|
-
module Spree
|
7
|
-
LineItem.class_eval do
|
8
|
-
# admin show line item price
|
9
|
-
def single_money
|
10
|
-
price = display_price.to_s
|
11
|
-
price += " (#{order.flow_line_item_price(self)})" if order.flow_order
|
12
|
-
price
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,179 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# `:display_total` modifications to display total prices beside Spree default. Example: https://i.imgur.com/7v2ix2G.png
|
4
|
-
module Spree # rubocop:disable Metrics/ModuleLength
|
5
|
-
# Added flow specific methods to Spree::Order
|
6
|
-
Order.class_eval do
|
7
|
-
serialize :meta, ActiveRecord::Coders::JSON.new(symbolize_keys: true)
|
8
|
-
|
9
|
-
store_accessor :meta, :flow_data
|
10
|
-
|
11
|
-
before_save :sync_to_flow_io
|
12
|
-
after_touch :sync_to_flow_io
|
13
|
-
|
14
|
-
def sync_to_flow_io
|
15
|
-
return unless zone&.flow_io_active_experience? && state == 'cart' && line_items.size > 0
|
16
|
-
|
17
|
-
flow_io_order = FlowcommerceSpree::OrderSync.new(order: self)
|
18
|
-
flow_io_order.build_flow_request
|
19
|
-
flow_io_order.synchronize! if flow_data['digest'] != flow_io_order.digest
|
20
|
-
end
|
21
|
-
|
22
|
-
def display_total
|
23
|
-
price = FlowcommerceSpree::Api.format_default_price total
|
24
|
-
price += " (#{flow_total})" if flow_order
|
25
|
-
price.html_safe
|
26
|
-
end
|
27
|
-
|
28
|
-
def flow_order
|
29
|
-
return unless flow_data&.[]('order')
|
30
|
-
|
31
|
-
Hashie::Mash.new flow_data['order']
|
32
|
-
end
|
33
|
-
|
34
|
-
# accepts line item, usually called from views
|
35
|
-
def flow_line_item_price(line_item, total = false)
|
36
|
-
result = if flow_order
|
37
|
-
id = line_item.variant.sku
|
38
|
-
|
39
|
-
lines = flow_order.lines || []
|
40
|
-
item = lines.find { |el| el['item_number'] == id }
|
41
|
-
|
42
|
-
return 'n/a' unless item
|
43
|
-
|
44
|
-
total ? item['total']['label'] : item['price']['label']
|
45
|
-
else
|
46
|
-
FlowcommerceSpree::Api.format_default_price(line_item.price * (total ? line_item.quantity : 1))
|
47
|
-
end
|
48
|
-
|
49
|
-
# add line item promo
|
50
|
-
# promo_total, adjustment_total
|
51
|
-
result += " (#{FlowcommerceSpree::Api.format_default_price(line_item.promo_total)})" if line_item.promo_total > 0
|
52
|
-
|
53
|
-
result
|
54
|
-
end
|
55
|
-
|
56
|
-
# prepares array of prices that can be easily renderd in templates
|
57
|
-
def flow_cart_breakdown
|
58
|
-
prices = []
|
59
|
-
|
60
|
-
price_model = Struct.new(:name, :label)
|
61
|
-
|
62
|
-
if flow_order
|
63
|
-
# duty, vat, ...
|
64
|
-
unless flow_order.prices
|
65
|
-
message = Flow::Error.format_order_message flow_order
|
66
|
-
raise Flow::Error, message
|
67
|
-
end
|
68
|
-
|
69
|
-
flow_order.prices.each do |price|
|
70
|
-
prices.push price_model.new(price['name'], price['label'])
|
71
|
-
end
|
72
|
-
else
|
73
|
-
price_elements =
|
74
|
-
%i[item_total adjustment_total included_tax_total additional_tax_total tax_total shipment_total promo_total]
|
75
|
-
price_elements.each do |el|
|
76
|
-
price = send(el)
|
77
|
-
if price > 0
|
78
|
-
label = FlowcommerceSpree::Api.format_default_price price
|
79
|
-
prices.push price_model.new(el.to_s.humanize.capitalize, label)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# discount is applied and we allways show it in default currency
|
84
|
-
if adjustment_total != 0
|
85
|
-
formated_discounted_price = FlowcommerceSpree::Api.format_default_price adjustment_total
|
86
|
-
prices.push price_model.new('Discount', formated_discounted_price)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# total
|
91
|
-
prices.push price_model.new(Spree.t(:total), flow_total)
|
92
|
-
|
93
|
-
prices
|
94
|
-
end
|
95
|
-
|
96
|
-
# shows localized total, if possible. if not, fall back to Spree default
|
97
|
-
def flow_total
|
98
|
-
# r flow_order.total.label
|
99
|
-
price = flow_order&.total&.label
|
100
|
-
price || FlowcommerceSpree::Api.format_default_price(total)
|
101
|
-
end
|
102
|
-
|
103
|
-
def flow_experience
|
104
|
-
model = Struct.new(:key)
|
105
|
-
model.new flow_order.experience.key
|
106
|
-
rescue StandardError => _e
|
107
|
-
model.new ENV.fetch('FLOW_BASE_COUNTRY')
|
108
|
-
end
|
109
|
-
|
110
|
-
def flow_io_experience_key
|
111
|
-
flow_data&.[]('exp')
|
112
|
-
end
|
113
|
-
|
114
|
-
def flow_io_experience_from_zone
|
115
|
-
self.flow_data = (flow_data || {}).merge!('exp' => zone.flow_io_experience)
|
116
|
-
end
|
117
|
-
|
118
|
-
def flow_io_order_id
|
119
|
-
flow_data&.dig('order', 'id')
|
120
|
-
end
|
121
|
-
|
122
|
-
def flow_io_attributes
|
123
|
-
flow_data&.dig('order', 'attributes') || {}
|
124
|
-
end
|
125
|
-
|
126
|
-
def add_user_consent_to_flow_data(consent, value)
|
127
|
-
self.flow_data['order'] ||= {}
|
128
|
-
self.flow_data['order']['attributes'] ||= {}
|
129
|
-
self.flow_data['order']['attributes'][consent] = value
|
130
|
-
end
|
131
|
-
|
132
|
-
def add_user_uuid_to_flow_data
|
133
|
-
self.flow_data['order'] ||= {}
|
134
|
-
self.flow_data['order']['attributes'] ||= {}
|
135
|
-
self.flow_data['order']['attributes']['user_uuid'] = user&.uuid
|
136
|
-
end
|
137
|
-
|
138
|
-
def flow_io_user_uuid
|
139
|
-
flow_data&.dig('order', 'attributes', 'user_uuid')
|
140
|
-
end
|
141
|
-
|
142
|
-
def checkout_url
|
143
|
-
"https://checkout.flow.io/#{FlowcommerceSpree::ORGANIZATION}/checkout/#{number}/" \
|
144
|
-
"contact-info?flow_session_id=#{flow_data['session_id']}"
|
145
|
-
end
|
146
|
-
|
147
|
-
# clear invalid zero amount payments. Solidus bug?
|
148
|
-
def clear_zero_amount_payments!
|
149
|
-
# class attribute that can be set to true
|
150
|
-
return unless Flow::Order.clear_zero_amount_payments
|
151
|
-
|
152
|
-
payments.where(amount: 0, state: %w[invalid processing pending]).map(&:destroy)
|
153
|
-
end
|
154
|
-
|
155
|
-
def flow_order_authorized?
|
156
|
-
flow_data&.[]('authorization') ? true : false
|
157
|
-
end
|
158
|
-
|
159
|
-
def flow_order_captured?
|
160
|
-
flow_data['capture'] ? true : false
|
161
|
-
end
|
162
|
-
|
163
|
-
# completes order and sets all states to finalized and complete
|
164
|
-
# used when we have confirmed capture from Flow API or PayPal
|
165
|
-
def flow_finalize!
|
166
|
-
finalize! unless state == 'complete'
|
167
|
-
update_column :payment_state, 'paid' if payment_state != 'paid'
|
168
|
-
update_column :state, 'complete' if state != 'complete'
|
169
|
-
end
|
170
|
-
|
171
|
-
def flow_payment_method
|
172
|
-
if flow_data['payment_type'] == 'paypal'
|
173
|
-
'paypal'
|
174
|
-
else
|
175
|
-
'cc' # creait card is default
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
<%
|
2
|
-
# render text email in console. parts[1] for html body
|
3
|
-
# puts Spree::OrderMailer.confirm_email(Spree::Order.last).body.parts[0].body
|
4
|
-
|
5
|
-
@prices = @order.flow_cart_breakdown
|
6
|
-
@total_price = @prices.pop
|
7
|
-
%>
|
8
|
-
|
9
|
-
<style>
|
10
|
-
table.order td { padding: 4px; border-top: 1px solid #bbb; }
|
11
|
-
</style>
|
12
|
-
|
13
|
-
<h6>Dear <%= @order.bill_address.firstname %></h6>
|
14
|
-
|
15
|
-
<br>
|
16
|
-
<br>
|
17
|
-
|
18
|
-
<p><%= Spree.t('order_mailer.confirm_email.instructions') %></p>
|
19
|
-
<p><%= Spree.t('order_mailer.confirm_email.order_summary') %></p>
|
20
|
-
|
21
|
-
<table class="order">
|
22
|
-
<tr>
|
23
|
-
<th>Product</th>
|
24
|
-
<th width="100" align="right">Price</th>
|
25
|
-
<th width="80" align="center">Quantity</th>
|
26
|
-
<th width="100" align="right">Total</th>
|
27
|
-
</tr>
|
28
|
-
<% @order.line_items.each do |line_item| %>
|
29
|
-
<tr>
|
30
|
-
<td><%= line_item.variant.product.name %></td>
|
31
|
-
<td align="right"><%= @order.flow_line_item_price(line_item) %></td>
|
32
|
-
<td align="center"><%= line_item.quantity %></td>
|
33
|
-
<td align="right"><%= @order.flow_line_item_price(line_item, :with_quantity) %></td>
|
34
|
-
</tr>
|
35
|
-
<% end %>
|
36
|
-
</table>
|
37
|
-
|
38
|
-
<br>
|
39
|
-
|
40
|
-
<p><b>Total</b></p>
|
41
|
-
|
42
|
-
<table class="order">
|
43
|
-
|
44
|
-
<% @prices.each do |price| %>
|
45
|
-
<tr><td width="120"><%= price.name.capitalize %></td><td align="right"><%= price.label %></td></tr>
|
46
|
-
<% end %>
|
47
|
-
|
48
|
-
<tr>
|
49
|
-
<td><%= Spree.t(:total) %></td>
|
50
|
-
<td align="right"><b><%= @total_price.label %></b></td>
|
51
|
-
</tr>
|
52
|
-
<tr>
|
53
|
-
<td>Payment method</td>
|
54
|
-
<td align="right"><%= @order.flow_payment_method == 'paypal' ? 'PayPal' : 'Credit Card' %></td>
|
55
|
-
</tr>
|
56
|
-
</table>
|
57
|
-
|
58
|
-
<br>
|
59
|
-
|
60
|
-
<% ['ship', 'bill'].each do |name|
|
61
|
-
address = @order.send('%s_address' % name)
|
62
|
-
%>
|
63
|
-
<p><b><%= name.capitalize %>ing address</b></p>
|
64
|
-
|
65
|
-
<table class="order">
|
66
|
-
<tr>
|
67
|
-
<td>Full name</td>
|
68
|
-
<td><%= address.firstname %> <%= address.lastname %></td>
|
69
|
-
</tr>
|
70
|
-
<tr>
|
71
|
-
<td>Address</td>
|
72
|
-
<td><%= address.address1 %></td>
|
73
|
-
</tr>
|
74
|
-
<tr>
|
75
|
-
<td>City</td>
|
76
|
-
<td><%= address.city %></td>
|
77
|
-
</tr>
|
78
|
-
<tr>
|
79
|
-
<td>Country</td>
|
80
|
-
<td><%= address.country.name rescue '-' %>, <%= address.state.name rescue '-' %></td>
|
81
|
-
</tr>
|
82
|
-
</table>
|
83
|
-
<br />
|
84
|
-
<% end %>
|
85
|
-
|
86
|
-
<p><%= Spree.t('order_mailer.confirm_email.thanks') %></p>
|
@@ -1,38 +0,0 @@
|
|
1
|
-
<%= Spree.t('order_mailer.confirm_email.dear_customer') %>
|
2
|
-
|
3
|
-
<%= Spree.t('order_mailer.confirm_email.instructions') %>
|
4
|
-
|
5
|
-
============================================================
|
6
|
-
<%= Spree.t('order_mailer.confirm_email.order_summary') %>
|
7
|
-
============================================================
|
8
|
-
<% @order.line_items.each do |item| %>
|
9
|
-
<%= item.variant.sku %> <%= raw(item.variant.product.name) %> <%= raw(item.variant.options_text) -%> (<%=item.quantity%>) @ <%= item.single_money %> = <%= @order.flow_line_item_price(line_item, :with_quantity) %>
|
10
|
-
<% end %>
|
11
|
-
============================================================
|
12
|
-
<%= Spree.t('order_mailer.confirm_email.subtotal', :subtotal => @order.display_item_total) %>
|
13
|
-
<% if @order.line_item_adjustments.exists? %>
|
14
|
-
<% if @order.all_adjustments.promotion.eligible.exists? %>
|
15
|
-
<% @order.all_adjustments.promotion.eligible.group_by(&:label).each do |label, adjustments| %>
|
16
|
-
<%= Spree.t(:promotion) %>: <%= label %> <%= Spree::Money.new(adjustments.sum(&:amount), currency: @order.currency) %>
|
17
|
-
<% end %>
|
18
|
-
<% end %>
|
19
|
-
<% end %>
|
20
|
-
|
21
|
-
<% @order.shipments.group_by { |s| s.selected_shipping_rate.try(:name) }.each do |name, shipments| %>
|
22
|
-
<%= Spree.t(:shipping) %>: <%= name %> <%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: @order.currency) %>
|
23
|
-
<% end %>
|
24
|
-
|
25
|
-
<% if @order.all_adjustments.eligible.tax.exists? %>
|
26
|
-
<% @order.all_adjustments.eligible.tax.group_by(&:label).each do |label, adjustments| %>
|
27
|
-
<%= Spree.t(:tax) %>: <%= label %> <%= Spree::Money.new(adjustments.sum(&:amount), currency: @order.currency) %>
|
28
|
-
<% end %>
|
29
|
-
<% end %>
|
30
|
-
|
31
|
-
<% @order.adjustments.eligible.each do |adjustment| %>
|
32
|
-
<% next if (adjustment.source_type == 'Spree::TaxRate') and (adjustment.amount == 0) %>
|
33
|
-
<%= adjustment.label %> <%= adjustment.display_amount %>
|
34
|
-
<% end %>
|
35
|
-
============================================================
|
36
|
-
<%= Spree.t('order_mailer.confirm_email.total', :total => @order.display_total) %>
|
37
|
-
|
38
|
-
<%= Spree.t('order_mailer.confirm_email.thanks') %>
|
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
|