flowcommerce_spree 0.0.2 → 0.0.3
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 +13 -9
- data/SPREE_FLOW.md +6 -28
- data/app/controllers/concerns/current_zone_loader_decorator.rb +37 -23
- data/app/controllers/flowcommerce_spree/webhooks_controller.rb +15 -3
- data/app/controllers/users/sessions_controller_decorator.rb +11 -0
- data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +19 -8
- 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 +37 -0
- data/app/models/spree/flow_io_variant_decorator.rb +2 -2
- data/app/models/spree/gateway/{spree_flow_gateway.rb → flow_io.rb} +2 -2
- data/app/models/spree/order_decorator.rb +75 -10
- data/app/models/spree/promotion_handler/coupon_decorator.rb +1 -1
- data/app/models/spree/zones/flow_io_product_zone_decorator.rb +4 -0
- data/app/models/tracking/setup_decorator.rb +40 -0
- data/app/services/flowcommerce_spree/order_sync.rb +137 -57
- data/config/rails_best_practices.yml +51 -0
- data/lib/flowcommerce_spree.rb +12 -2
- data/lib/flowcommerce_spree/engine.rb +28 -3
- data/lib/flowcommerce_spree/logging_http_client.rb +11 -9
- data/lib/flowcommerce_spree/session.rb +16 -11
- data/lib/flowcommerce_spree/test_support.rb +7 -0
- data/lib/flowcommerce_spree/version.rb +1 -1
- data/lib/flowcommerce_spree/webhook_service.rb +126 -40
- metadata +24 -4
- data/config/initializers/flowcommerce_spree.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51a668ee3cc70d0bc9bd8c7662a972f086e06dcdcf4c68df2177e94818dfb820
|
4
|
+
data.tar.gz: aa9ff17e57cd19452736af11d51bd1905c4dd7e66bb461b5dff017fc5dea0b0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 024a29a6fc47f932e432f2477f9a1f3b520af7cc10b7a85eb35613328276d5390a682187151217c0527b20435431f78e8cc55255d95298620bfb5077c7ed5011
|
7
|
+
data.tar.gz: b6d9485612e360ed50caabfab537baf9583feec384607b4a890c1ab1fd9fc48cd9ea3954562aac828f4a858682ad1515ae7f2b9bf05a8a501ff8abf96c28f972
|
data/README.md
CHANGED
@@ -11,32 +11,36 @@ All flowcommerce_spree code is located in the ./app and ./lib folders.
|
|
11
11
|
gem 'flowcommerce_spree', git: 'https://github.com/mejuri-inc/flowcommerce_spree'
|
12
12
|
```
|
13
13
|
|
14
|
-
- If the main application's Rails version is less than 4.2, add also
|
15
|
-
-postgres-json` gem (
|
14
|
+
- If the main application's Rails version is less than 4.2, add also to main application's Gemfile the `activerecord
|
15
|
+
-postgres-json` gem (at least version 0.2.3):
|
16
16
|
|
17
17
|
```
|
18
|
-
gem 'activerecord-postgres-json',
|
18
|
+
gem 'activerecord-postgres-json', '>= 0.2.3'
|
19
19
|
```
|
20
|
-
|
21
20
|
|
22
21
|
- Run `bundle install`.
|
23
22
|
|
24
|
-
- Define this additional ENV variables. You will find them in
|
23
|
+
- Define this additional ENV variables. You will find all of them, except FLOW_MOUNT_PATH in
|
25
24
|
[Flow console](https://console.flow.io/org_account_name/organization/integrations):
|
26
25
|
|
27
26
|
```
|
28
27
|
FLOW_TOKEN='SUPERsecretTOKEN' # API_KEY
|
29
28
|
FLOW_ORGANIZATION='spree-app-sandbox'
|
30
29
|
FLOW_BASE_COUNTRY='usa'
|
30
|
+
# The path to which the FlowcommerceSpree engine will be mounted (default, if this variable is missing, will be the
|
31
|
+
# '/flow' path)
|
32
|
+
FLOW_MOUNT_PATH='/flow'
|
31
33
|
```
|
32
34
|
|
33
|
-
-
|
35
|
+
- To enable payments with the FlowCommerce engine, the payment method `flow.io` with `Spree::Gateway::FlowIo` should be
|
36
|
+
added in the Spree Admin. This payment method is automatically registered in the gem in an after_initialize Rails
|
37
|
+
engine callback:
|
34
38
|
|
35
39
|
```
|
36
|
-
#
|
40
|
+
# lib/flowcommerce_spree/engine.rb
|
37
41
|
config.after_initialize do |app|
|
38
42
|
# init Flow payments as an option
|
39
|
-
app.config.spree.payment_methods << Spree::Gateway::
|
43
|
+
app.config.spree.payment_methods << Spree::Gateway::FlowIo
|
40
44
|
end
|
41
45
|
```
|
42
46
|
|
@@ -80,7 +84,7 @@ Decorators are used extensively across the gem to modify or add behaviour of sev
|
|
80
84
|
properly deal with the precedence in the Ruby ancestor chain, the `class_eval`, `include` and `prepend` methods are
|
81
85
|
being used, depending on the level of modification.
|
82
86
|
|
83
|
-
### Spree::
|
87
|
+
### Spree::Gateway::FlowIo
|
84
88
|
|
85
89
|
Adapter for Spree, that allows using [Flow.io](https://www.flow.io) as payment gateway. Flow is PCI compliant payment processor.
|
86
90
|
|
data/SPREE_FLOW.md
CHANGED
@@ -2,40 +2,19 @@
|
|
2
2
|
|
3
3
|
Integration of Spree with Flow, how it is done.
|
4
4
|
|
5
|
-
|
5
|
+
## Installation
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
Add the following lines to `./config/application.rb` :
|
10
|
-
|
11
|
-
```
|
12
|
-
config.to_prepare do
|
13
|
-
# add all flow libs
|
14
|
-
overload = Dir.glob('./app/flow/**/*.rb')
|
15
|
-
overload.reverse.each { |c| require(c) }
|
16
|
-
end
|
17
|
-
|
18
|
-
config.after_initialize do |app|
|
19
|
-
# init Flow payments as an option
|
20
|
-
app.config.spree.payment_methods << Spree::Gateway::Flow
|
21
|
-
end
|
22
|
-
```
|
23
|
-
|
24
|
-
Additional configuration could be adjusted in the gem's initializer. For example, the following file could be created in the main application:
|
7
|
+
Additional configuration could be adjusted in the gem's initializer. For example, the following file could be created
|
8
|
+
in the main application, which would add additional attributes of spree_variants to be imported/exported to flow.io:
|
25
9
|
|
26
10
|
```
|
27
11
|
# ./config/initializers/flowcommerce_spree.rb
|
28
12
|
|
29
|
-
FlowcommerceSpree.
|
30
|
-
|
31
|
-
|
13
|
+
FlowcommerceSpree::Config.additional_attributes =
|
14
|
+
{ spree_variants: { country_of_origin: { import: true, export: :optional },
|
15
|
+
customs_description: { import: true, export: :optional, export_name: 'materials' } } }
|
32
16
|
```
|
33
17
|
|
34
|
-
### Configurable settings
|
35
|
-
|
36
|
-
1. experience_associator - this attribute could be assigned, if necessary, a service object to perform some
|
37
|
-
additional association actions when upserting a FlowcommerceSpree::Experience model
|
38
|
-
|
39
18
|
## Things to take into account
|
40
19
|
|
41
20
|
ActiveMerchant is not supporting sessions and orders, natively. If one wants
|
@@ -131,4 +110,3 @@ By default Flow Admin (on /admin/flow) is anybody that is Spree admin.
|
|
131
110
|
|
132
111
|
This way we provide good frontend info, some integration notes in realtime as opposed to running
|
133
112
|
rake tests to check for integrity of Flow integration.
|
134
|
-
|
@@ -3,29 +3,52 @@
|
|
3
3
|
CurrentZoneLoader.module_eval do
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
def
|
6
|
+
def current_zone
|
7
|
+
return @current_zone if defined?(@current_zone)
|
8
|
+
|
9
|
+
@current_zone = if (session_region_name = session['region']&.[]('name'))
|
10
|
+
Spree::Zones::Product.find_by(name: session_region_name)
|
11
|
+
elsif request_iso_code.present?
|
12
|
+
@current_zone = flow_zone
|
13
|
+
@current_zone ||= Spree::Country.find_by(iso: request_iso_code)&.product_zones&.active&.first
|
14
|
+
end
|
15
|
+
|
16
|
+
@current_zone ||= Spree::Zones::Product.find_by(name: 'International') ||
|
17
|
+
Spree::Zones::Product.new(name: 'International', taxon_ids: [], currencies: %w[USD CAD])
|
18
|
+
|
19
|
+
current_zone_name = @current_zone.name
|
20
|
+
session['region'] = { name: current_zone_name, available_currencies: @current_zone.available_currencies,
|
21
|
+
request_iso_code: request_iso_code }
|
22
|
+
|
23
|
+
RequestStore.store[:session] = session
|
24
|
+
Rails.logger.debug("Using product zone: #{current_zone_name}")
|
25
|
+
@current_zone
|
26
|
+
end
|
27
|
+
|
28
|
+
def flow_zone # rubocop:disable Metrics/AbcSize
|
7
29
|
return unless Spree::Zones::Product.active
|
8
30
|
.where("meta -> 'flow_data' ->> 'country' = ?",
|
9
31
|
ISO3166::Country[request_iso_code]&.alpha3).exists?
|
10
32
|
|
11
|
-
request_ip =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
flow_io_session = FlowcommerceSpree::Session
|
19
|
-
.new(ip: request_ip, visitor: visitor_id_for_flow_io)
|
33
|
+
request_ip = if Rails.env.production?
|
34
|
+
request.ip
|
35
|
+
else
|
36
|
+
Spree::Config[:debug_request_ip_address] || request.ip
|
37
|
+
# Germany ip: 85.214.132.117, Sweden ip: 62.20.0.196, Moldova ip: 89.41.76.29
|
38
|
+
end
|
39
|
+
flow_io_session = FlowcommerceSpree::Session.create(ip: request_ip, visitor: visitor_id_for_flow_io)
|
20
40
|
# :create method will issue a request to flow.io. The experience, contained in the
|
21
41
|
# response, will be available in the session object - flow_io_session.experience
|
22
|
-
|
23
|
-
zone = Spree::Zones::Product.active.find_by(name: flow_io_session.experience&.key&.titleize)
|
24
|
-
|
42
|
+
|
43
|
+
if (zone = Spree::Zones::Product.active.find_by(name: flow_io_session.experience&.key&.titleize))
|
44
|
+
session['_f60_session'] = flow_io_session.id
|
45
|
+
session['_f60_expires_at'] = flow_io_session.expires_at.to_s
|
46
|
+
end
|
47
|
+
|
25
48
|
zone
|
26
49
|
end
|
27
50
|
|
28
|
-
# composes an unique
|
51
|
+
# composes an unique visitor id for FlowcommerceSpree::Session model
|
29
52
|
def visitor_id_for_flow_io
|
30
53
|
guest_token = cookies.signed[:guest_token]
|
31
54
|
uid = if guest_token
|
@@ -37,13 +60,4 @@ CurrentZoneLoader.module_eval do
|
|
37
60
|
|
38
61
|
"session-#{uid}"
|
39
62
|
end
|
40
|
-
|
41
|
-
def fetch_product_for_zone(product)
|
42
|
-
Rails.cache.fetch(
|
43
|
-
"product_zone_#{current_zone.name}_#{product.sku}", expires_in: 1.day,
|
44
|
-
race_condition_ttl: 10.seconds, compress: true
|
45
|
-
) do
|
46
|
-
Spree::Zones::Product.find_product_for_zone(product, current_zone)
|
47
|
-
end
|
48
|
-
end
|
49
63
|
end
|
@@ -2,14 +2,17 @@
|
|
2
2
|
|
3
3
|
module FlowcommerceSpree
|
4
4
|
class WebhooksController < ActionController::Base
|
5
|
+
wrap_parameters false
|
5
6
|
respond_to :json
|
6
7
|
|
7
8
|
# forward all incoming requests to Flow WebhookService object
|
8
9
|
# /flow/event-target endpoint
|
9
10
|
def handle_flow_web_hook_event
|
10
|
-
|
11
|
-
result
|
12
|
-
|
11
|
+
result = check_organization
|
12
|
+
if result.blank?
|
13
|
+
webhook_result = WebhookService.process(params)
|
14
|
+
result[:error] = webhook_result.full_messages.join("\n") if webhook_result.errors.any?
|
15
|
+
end
|
13
16
|
rescue StandardError => e
|
14
17
|
result = { error: e.class.to_s, message: e.message, backtrace: e.backtrace }
|
15
18
|
ensure
|
@@ -21,5 +24,14 @@ module FlowcommerceSpree
|
|
21
24
|
end
|
22
25
|
render json: result.except(:backtrace), status: response_status
|
23
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def check_organization
|
31
|
+
org = params[:organization]
|
32
|
+
return {} if org == FlowcommerceSpree::ORGANIZATION
|
33
|
+
|
34
|
+
{ error: 'InvalidParam', message: "Organization '#{org}' is invalid!" }
|
35
|
+
end
|
24
36
|
end
|
25
37
|
end
|
@@ -12,16 +12,27 @@ module Spree
|
|
12
12
|
update_meta = @current_order.zone_id ? nil : true
|
13
13
|
@current_order.zone = current_zone
|
14
14
|
|
15
|
-
if @current_order.zone&.flow_io_active_experience?
|
16
|
-
@current_order.
|
17
|
-
|
15
|
+
if @current_order.zone&.flow_io_active_experience?
|
16
|
+
if @current_order.flow_io_experience_key.nil?
|
17
|
+
@current_order.flow_io_experience_from_zone
|
18
|
+
update_meta ||= true
|
19
|
+
end
|
20
|
+
order_flow_session_id = @current_order.flow_data['session_id']
|
21
|
+
order_session_expired = @current_order.flow_data['session_expires_at']
|
18
22
|
flow_io_session_id = session['_f60_session']
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
flow_io_session_expires = session['_f60_expires_at']
|
24
|
+
if flow_io_session_id.present?
|
25
|
+
if order_flow_session_id != flow_io_session_id &&
|
26
|
+
order_session_expired&.to_datetime.to_i < flow_io_session_expires&.to_datetime.to_i
|
27
|
+
@current_order.flow_data['session_id'] = flow_io_session_id
|
28
|
+
@current_order.flow_data['session_expires_at'] = flow_io_session_expires
|
29
|
+
@current_order.flow_data['checkout_token'] = nil
|
30
|
+
update_meta ||= true
|
31
|
+
end
|
32
|
+
elsif order_flow_session_id.present?
|
33
|
+
session['_f60_session'] = order_flow_session_id
|
34
|
+
session['_f60_expires_at'] = order_session_expired
|
23
35
|
end
|
24
|
-
update_meta = true
|
25
36
|
end
|
26
37
|
|
27
38
|
if @current_order.new_record?
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
Address.class_eval do
|
5
|
+
def prepare_from_flow_attributes(address_data)
|
6
|
+
self.attributes = {
|
7
|
+
first_name: address_data['first'],
|
8
|
+
last_name: address_data['last'],
|
9
|
+
phone: address_data['phone'],
|
10
|
+
address1: address_data['streets'][0],
|
11
|
+
address2: address_data['streets'][1],
|
12
|
+
zipcode: address_data['postal'],
|
13
|
+
city: address_data['city'],
|
14
|
+
state_name: address_data['province'] || 'something',
|
15
|
+
country: Spree::Country.find_by(iso3: address_data['country'])
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class Calculator
|
5
|
+
class FlowIo < Calculator::DefaultTax
|
6
|
+
def self.description
|
7
|
+
'FlowIO Calculator'
|
8
|
+
end
|
9
|
+
|
10
|
+
def compute_shipment_or_line_item(item)
|
11
|
+
order = item.order
|
12
|
+
|
13
|
+
if can_calculate_tax?(order)
|
14
|
+
flow_response = get_flow_tax_data(order)
|
15
|
+
tax_for_item(item, flow_response)
|
16
|
+
else
|
17
|
+
prev_tax_amount(item)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias compute_shipment compute_shipment_or_line_item
|
21
|
+
alias compute_line_item compute_shipment_or_line_item
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def prev_tax_amount(item)
|
26
|
+
if rate.included_in_price
|
27
|
+
item.included_tax_total
|
28
|
+
else
|
29
|
+
item.additional_tax_total
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def can_calculate_tax?(order)
|
34
|
+
return false if order.flow_data.blank?
|
35
|
+
return false if %w[cart address delivery].include?(order.state)
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_flow_tax_data(order)
|
41
|
+
flow_io_tax_response = Rails.cache.fetch(order.flow_tax_cache_key, time_to_idle: 5.minutes) do
|
42
|
+
FlowcommerceSpree.client.orders.get_allocations_by_number(FlowcommerceSpree::ORGANIZATION, order.number)
|
43
|
+
end
|
44
|
+
flow_io_tax_response
|
45
|
+
end
|
46
|
+
|
47
|
+
def tax_for_item(item, flow_response)
|
48
|
+
prev_tax_amount = prev_tax_amount(item)
|
49
|
+
return prev_tax_amount if flow_response.nil?
|
50
|
+
|
51
|
+
item_details = flow_response.details&.find do |el|
|
52
|
+
item.is_a?(Spree::LineItem) ? el.number == item.variant.sku : el.key.value == 'shipping'
|
53
|
+
end
|
54
|
+
price_components = rate.included_in_price ? item_details.included : item_details.not_included
|
55
|
+
|
56
|
+
amount = price_components&.find { |el| el.key.value == 'vat_item_price' }&.total&.amount
|
57
|
+
amount.present? && amount > 0 ? amount : prev_tax_amount
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class Calculator
|
5
|
+
module Shipping
|
6
|
+
class FlowIo < ShippingCalculator
|
7
|
+
def self.description
|
8
|
+
'FlowIO Calculator'
|
9
|
+
end
|
10
|
+
|
11
|
+
def compute_package(package)
|
12
|
+
flow_order = flow_order(package)
|
13
|
+
return unless flow_order
|
14
|
+
|
15
|
+
flow_order['prices'].find { |x| x['key'] == 'shipping' }['amount'] || 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_charge(_country)
|
19
|
+
0
|
20
|
+
end
|
21
|
+
|
22
|
+
def threshold
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def flow_order(package)
|
29
|
+
return @flow_order if defined?(@flow_order)
|
30
|
+
|
31
|
+
@flow_order = package.order.flow_data&.[]('order')
|
32
|
+
@flow_order
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -22,8 +22,8 @@ module Spree
|
|
22
22
|
raise ArgumentError, 'Value should be a hash' unless value.is_a?(Hash)
|
23
23
|
|
24
24
|
self.flow_data = flow_data || {}
|
25
|
-
self.flow_data['exp'] ||= {}
|
26
|
-
self.flow_data['exp'][exp] = value
|
25
|
+
self.flow_data['exp'] ||= {} # rubocop:disable Style/RedundantSelf
|
26
|
+
self.flow_data['exp'][exp] = value # rubocop:disable Style/RedundantSelf
|
27
27
|
end
|
28
28
|
|
29
29
|
# clears flow_data from the records
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# adapter for Spree that talks to activemerchant_flow
|
5
5
|
module Spree
|
6
6
|
class Gateway
|
7
|
-
class
|
7
|
+
class FlowIo < Gateway
|
8
8
|
def provider_class
|
9
9
|
self.class
|
10
10
|
end
|
@@ -81,7 +81,7 @@ module Spree
|
|
81
81
|
def profile_ensure_payment_method_is_present!
|
82
82
|
return if @credit_card.payment_method_id
|
83
83
|
|
84
|
-
flow_payment = Spree::PaymentMethod.where(active: true, type: 'Spree::Gateway::
|
84
|
+
flow_payment = Spree::PaymentMethod.where(active: true, type: 'Spree::Gateway::FlowIo').first
|
85
85
|
@credit_card.payment_method_id = flow_payment.id if flow_payment
|
86
86
|
end
|
87
87
|
|
@@ -11,6 +11,10 @@ module Spree # rubocop:disable Metrics/ModuleLength
|
|
11
11
|
before_save :sync_to_flow_io
|
12
12
|
after_touch :sync_to_flow_io
|
13
13
|
|
14
|
+
def flow_tax_cache_key
|
15
|
+
[number, 'flowcommerce', 'allocation', line_items.sum(:quantity)].join('-')
|
16
|
+
end
|
17
|
+
|
14
18
|
def sync_to_flow_io
|
15
19
|
return unless zone&.flow_io_active_experience? && state == 'cart' && line_items.size > 0
|
16
20
|
|
@@ -34,10 +38,7 @@ module Spree # rubocop:disable Metrics/ModuleLength
|
|
34
38
|
# accepts line item, usually called from views
|
35
39
|
def flow_line_item_price(line_item, total = false)
|
36
40
|
result = if flow_order
|
37
|
-
|
38
|
-
|
39
|
-
lines = flow_order.lines || []
|
40
|
-
item = lines.find { |el| el['item_number'] == id }
|
41
|
+
item = flow_order.lines&.find { |el| el['item_number'] == line_item.variant.sku }
|
41
42
|
|
42
43
|
return 'n/a' unless item
|
43
44
|
|
@@ -107,6 +108,10 @@ module Spree # rubocop:disable Metrics/ModuleLength
|
|
107
108
|
model.new ENV.fetch('FLOW_BASE_COUNTRY')
|
108
109
|
end
|
109
110
|
|
111
|
+
def flow_io_checkout_token
|
112
|
+
flow_data&.[]('checkout_token')
|
113
|
+
end
|
114
|
+
|
110
115
|
def flow_io_experience_key
|
111
116
|
flow_data&.[]('exp')
|
112
117
|
end
|
@@ -119,29 +124,40 @@ module Spree # rubocop:disable Metrics/ModuleLength
|
|
119
124
|
flow_data&.dig('order', 'id')
|
120
125
|
end
|
121
126
|
|
127
|
+
def flow_io_session_expires_at
|
128
|
+
flow_data&.[]('session_expires_at')&.to_datetime
|
129
|
+
end
|
130
|
+
|
122
131
|
def flow_io_attributes
|
123
132
|
flow_data&.dig('order', 'attributes') || {}
|
124
133
|
end
|
125
134
|
|
126
|
-
def
|
135
|
+
def add_flow_checkout_token(token)
|
136
|
+
self.flow_data ||= {}
|
137
|
+
self.flow_data['checkout_token'] = token
|
138
|
+
end
|
139
|
+
|
140
|
+
def flow_io_attribute_add(attr_key, value)
|
127
141
|
self.flow_data['order'] ||= {}
|
128
142
|
self.flow_data['order']['attributes'] ||= {}
|
129
|
-
self.flow_data['order']['attributes'][
|
143
|
+
self.flow_data['order']['attributes'][attr_key] = value
|
130
144
|
end
|
131
145
|
|
132
146
|
def add_user_uuid_to_flow_data
|
133
147
|
self.flow_data['order'] ||= {}
|
134
148
|
self.flow_data['order']['attributes'] ||= {}
|
135
|
-
self.flow_data['order']['attributes']['user_uuid'] = user&.uuid
|
149
|
+
self.flow_data['order']['attributes']['user_uuid'] = user&.uuid || ''
|
136
150
|
end
|
137
151
|
|
138
|
-
def
|
152
|
+
def flow_io_attr_user_uuid
|
139
153
|
flow_data&.dig('order', 'attributes', 'user_uuid')
|
140
154
|
end
|
141
155
|
|
142
156
|
def checkout_url
|
143
|
-
|
144
|
-
|
157
|
+
FlowcommerceSpree::OrderSync.new(order: self).synchronize!
|
158
|
+
|
159
|
+
checkout_token = flow_io_checkout_token
|
160
|
+
return "https://checkout.flow.io/tokens/#{checkout_token}" if checkout_token
|
145
161
|
end
|
146
162
|
|
147
163
|
# clear invalid zero amount payments. Solidus bug?
|
@@ -175,5 +191,54 @@ module Spree # rubocop:disable Metrics/ModuleLength
|
|
175
191
|
'cc' # creait card is default
|
176
192
|
end
|
177
193
|
end
|
194
|
+
|
195
|
+
def flow_customer_email
|
196
|
+
flow_data.dig('order', 'customer', 'email')
|
197
|
+
end
|
198
|
+
|
199
|
+
def flow_ship_address
|
200
|
+
flow_destination = flow_data.dig('order', 'destination')
|
201
|
+
return unless flow_destination.present?
|
202
|
+
|
203
|
+
flow_destination['first'] = flow_destination.dig('contact', 'name', 'first')
|
204
|
+
flow_destination['last'] = flow_destination.dig('contact', 'name', 'last')
|
205
|
+
flow_destination['phone'] = flow_destination.dig('contact', 'phone')
|
206
|
+
|
207
|
+
s_address = ship_address || build_ship_address
|
208
|
+
s_address.prepare_from_flow_attributes(flow_destination)
|
209
|
+
s_address
|
210
|
+
end
|
211
|
+
|
212
|
+
def flow_bill_address
|
213
|
+
flow_payment_address = flow_data.dig('order', 'payments')&.last&.[]('address')
|
214
|
+
return unless flow_payment_address
|
215
|
+
|
216
|
+
flow_payment_address['first'] = flow_payment_address.dig('name', 'first')
|
217
|
+
flow_payment_address['last'] = flow_payment_address.dig('name', 'last')
|
218
|
+
flow_payment_address['phone'] = ship_address['phone']
|
219
|
+
|
220
|
+
b_address = bill_address || build_bill_address
|
221
|
+
b_address.prepare_from_flow_attributes(flow_payment_address)
|
222
|
+
b_address
|
223
|
+
end
|
224
|
+
|
225
|
+
def prepare_flow_addresses
|
226
|
+
address_attributes = {}
|
227
|
+
|
228
|
+
s_address = flow_ship_address
|
229
|
+
|
230
|
+
if s_address&.changes&.any?
|
231
|
+
s_address.save
|
232
|
+
address_attributes[:ship_address_id] = s_address.id unless ship_address_id
|
233
|
+
end
|
234
|
+
|
235
|
+
b_address = flow_bill_address
|
236
|
+
if b_address&.changes&.any?
|
237
|
+
b_address.save
|
238
|
+
address_attributes[:bill_address_id] = b_address.id unless bill_address_id
|
239
|
+
end
|
240
|
+
|
241
|
+
address_attributes
|
242
|
+
end
|
178
243
|
end
|
179
244
|
end
|