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.
- checksums.yaml +4 -4
- data/README.md +35 -6
- data/app/controllers/concerns/current_zone_loader_decorator.rb +11 -17
- 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 +16 -18
- data/app/controllers/users/sessions_controller_decorator.rb +19 -2
- data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +0 -16
- data/app/models/flowcommerce_spree/settings.rb +1 -0
- data/app/models/spree/address_decorator.rb +1 -1
- data/app/models/spree/calculator/flow_io.rb +24 -12
- data/app/models/spree/calculator/shipping/flow_io.rb +5 -2
- data/app/models/spree/flow_io_credit_card_decorator.rb +21 -0
- data/app/models/spree/flow_io_order_decorator.rb +181 -0
- data/app/models/spree/flow_io_product_decorator.rb +5 -0
- data/app/models/spree/flow_io_variant_decorator.rb +16 -6
- data/app/models/spree/gateway/flow_io.rb +61 -24
- data/app/models/spree/{credit_card_decorator.rb → payment_capture_event_decorator.rb} +1 -1
- data/app/models/spree/zones/flow_io_product_zone_decorator.rb +4 -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 -21
- data/app/services/flowcommerce_spree/import_item.rb +45 -0
- data/app/services/flowcommerce_spree/order_sync.rb +50 -222
- 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/app/workers/flowcommerce_spree/import_item_worker.rb +24 -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 +6 -2
- data/lib/flowcommerce_spree/engine.rb +6 -1
- data/lib/flowcommerce_spree/experience_service.rb +1 -27
- data/lib/flowcommerce_spree/logging_http_client.rb +29 -13
- data/lib/flowcommerce_spree/session.rb +5 -25
- data/lib/flowcommerce_spree/version.rb +1 -1
- data/lib/tasks/flowcommerce_spree.rake +4 -1
- metadata +77 -28
- data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
- data/app/models/spree/line_item_decorator.rb +0 -15
- data/app/models/spree/order_decorator.rb +0 -244
- 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/lib/flow/error.rb +0 -73
- data/lib/flow/pay_pal.rb +0 -25
- data/lib/flowcommerce_spree/webhook_service.rb +0 -184
- 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
|
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
|