flowcommerce_spree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +91 -0
  4. data/Rakefile +33 -0
  5. data/SPREE_FLOW.md +134 -0
  6. data/app/assets/javascripts/flowcommerce_spree/application.js +13 -0
  7. data/app/assets/stylesheets/flowcommerce_spree/application.css +15 -0
  8. data/app/controllers/concerns/current_zone_loader_decorator.rb +49 -0
  9. data/app/controllers/flowcommerce_spree/webhooks_controller.rb +25 -0
  10. data/app/helpers/flowcommerce_spree/application_helper.rb +6 -0
  11. data/app/helpers/spree/admin/orders_helper_decorator.rb +17 -0
  12. data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +53 -0
  13. data/app/mailers/spree/spree_order_mailer_decorator.rb +24 -0
  14. data/app/models/flowcommerce_spree/settings.rb +8 -0
  15. data/app/models/spree/credit_card_decorator.rb +9 -0
  16. data/app/models/spree/flow_io_product_decorator.rb +91 -0
  17. data/app/models/spree/flow_io_variant_decorator.rb +205 -0
  18. data/app/models/spree/gateway/spree_flow_gateway.rb +116 -0
  19. data/app/models/spree/line_item_decorator.rb +15 -0
  20. data/app/models/spree/order_decorator.rb +179 -0
  21. data/app/models/spree/promotion_decorator.rb +10 -0
  22. data/app/models/spree/promotion_handler/coupon_decorator.rb +30 -0
  23. data/app/models/spree/spree_user_decorator.rb +15 -0
  24. data/app/models/spree/taxon_decorator.rb +37 -0
  25. data/app/models/spree/zone_decorator.rb +7 -0
  26. data/app/models/spree/zones/flow_io_product_zone_decorator.rb +55 -0
  27. data/app/services/flowcommerce_spree/import_experience_items.rb +76 -0
  28. data/app/services/flowcommerce_spree/import_experiences.rb +37 -0
  29. data/app/services/flowcommerce_spree/order_sync.rb +231 -0
  30. data/app/views/layouts/flowcommerce_spree/application.html.erb +14 -0
  31. data/app/views/spree/admin/payments/index.html.erb +28 -0
  32. data/app/views/spree/admin/promotions/edit.html.erb +57 -0
  33. data/app/views/spree/admin/shared/_order_summary.html.erb +44 -0
  34. data/app/views/spree/admin/shared/_order_summary_flow.html.erb +13 -0
  35. data/app/views/spree/order_mailer/confirm_email.html.erb +86 -0
  36. data/app/views/spree/order_mailer/confirm_email.text.erb +38 -0
  37. data/config/initializers/flowcommerce_spree.rb +7 -0
  38. data/config/routes.rb +5 -0
  39. data/db/migrate/20201021160159_add_type_and_meta_to_spree_zone.rb +23 -0
  40. data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +17 -0
  41. data/db/migrate/20201022173210_add_zone_type_to_spree_zone_members.rb +24 -0
  42. data/db/migrate/20201022174252_add_kind_to_zone.rb +22 -0
  43. data/lib/flow/error.rb +73 -0
  44. data/lib/flow/pay_pal.rb +25 -0
  45. data/lib/flow/simple_gateway.rb +115 -0
  46. data/lib/flowcommerce_spree.rb +31 -0
  47. data/lib/flowcommerce_spree/api.rb +48 -0
  48. data/lib/flowcommerce_spree/engine.rb +27 -0
  49. data/lib/flowcommerce_spree/experience_service.rb +65 -0
  50. data/lib/flowcommerce_spree/logging_http_client.rb +43 -0
  51. data/lib/flowcommerce_spree/logging_http_handler.rb +15 -0
  52. data/lib/flowcommerce_spree/refresher.rb +81 -0
  53. data/lib/flowcommerce_spree/session.rb +71 -0
  54. data/lib/flowcommerce_spree/version.rb +5 -0
  55. data/lib/flowcommerce_spree/webhook_service.rb +98 -0
  56. data/lib/simple_csv_writer.rb +44 -0
  57. data/lib/tasks/flowcommerce_spree.rake +289 -0
  58. metadata +220 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6893ddfb8f021ff6400c0bbe31fc6b2c532886892730a1c9097d172944a8eca8
4
+ data.tar.gz: 9d3a1b190708053a5ad664588abe553617cf07a02ce6fb8f8b2b9d8d17b393a7
5
+ SHA512:
6
+ metadata.gz: 531a87c9a666b3057d16983c3e6168492ac124112a881821891e3bb2174f7e5589785301e023348f3bb06ef2ea105961f20a6a2aaa884e9845e92896973586d7
7
+ data.tar.gz: c84a3cb370744c3313b04cdc513d38d70ea0aaa01e7e09470bdf768f77d41fdb0c4bb9df240bbe4fec58adc4068b96d64fa538a315d73e8a361a1f718ecc6b46
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Aurel Branzeanu
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ <img src="https://i.imgur.com/tov8bTw.png" alt="flowcommerce_spree" style="float:right">
2
+
3
+ # Flow.io < - > Spree adapter
4
+
5
+ All flowcommerce_spree code is located in the ./app and ./lib folders.
6
+
7
+ ## Installation
8
+ - Add the gem to main application's Gemfile:
9
+
10
+ ```
11
+ gem 'flowcommerce_spree', git: 'https://github.com/mejuri-inc/flowcommerce_spree'
12
+ ```
13
+
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 (the mejuri-inc fork allows using a recent Rake version:
16
+
17
+ ```
18
+ gem 'activerecord-postgres-json', git: 'https://github.com/mejuri-inc/activerecord-postgres-json'
19
+ ```
20
+
21
+
22
+ - Run `bundle install`.
23
+
24
+ - Define this additional ENV variables. You will find them in
25
+ [Flow console](https://console.flow.io/org_account_name/organization/integrations):
26
+
27
+ ```
28
+ FLOW_TOKEN='SUPERsecretTOKEN' # API_KEY
29
+ FLOW_ORGANIZATION='spree-app-sandbox'
30
+ FLOW_BASE_COUNTRY='usa'
31
+ ```
32
+
33
+ - The only piece of code that is needed to enable payments with the FlowCommerce engine
34
+
35
+ ```
36
+ # config/application.rb
37
+ config.after_initialize do |app|
38
+ # init Flow payments as an option
39
+ app.config.spree.payment_methods << Spree::Gateway::Flow
40
+ end
41
+ ```
42
+
43
+ - To see and optionally invoke the list of FlowCommerce tasks, run `bundle exec rake flowcommerce_spree:list_tasks
44
+ `. Any task from the list could be invoked, typing at the `Type the task number to be invoked:` prompt the task
45
+ number, or from a terminal prompt, in the main application's root folder, running `bundle exec rake {task_name}`
46
+
47
+ - Run the `flowcommerce_spree:install:migrations` task to copy the DB migrations' file into the main application's
48
+ `db/migrate` folder.
49
+
50
+ - Run `bundle exec rake db:migrate SCOPE=flowcommerce_spree
51
+ ` from a terminal prompt. This will add an `meta` jsonb column to the Spree::CreditCard, Spree::Product,
52
+ Spree::Variant, Spree::Order, Spree::Promotion models' DB tables, if there is not yet such a column defined.
53
+
54
+ - If the main application's Rails version is less than 4.2, add the JSON serializer for the `meta` column to the
55
+ affected models' decorators (Spree::CreditCard, Spree::Product, Spree::Variant, Spree::Order, Spree::Promotion models):
56
+
57
+ `serialize :flow_data, ActiveRecord::Coders::JSON.new(symbolize_keys: true)`
58
+
59
+
60
+
61
+ ## Flow API specific
62
+
63
+ Classes that begin with Flow are responsible for communicating with flow API.
64
+
65
+ ### Flow
66
+
67
+ Helper class that offers low level flow api access and few helper methods.
68
+
69
+ ### FlowcommerceSpree::ExperienceService
70
+
71
+ Responsible for selecting current experience. You have to define available experiences in flow console.
72
+
73
+ ### Flow::Order
74
+
75
+ Maintain and synchronizes Spree::Order with Flow API.
76
+
77
+ ### Flow::Session
78
+
79
+ Every shop user has a session. This class helps in creating and maintaining session with Flow.
80
+
81
+ ## Decorators
82
+
83
+ Decorators are found in ./app/flow/decorators folders and they decorate Spree models with Flow specific methods.
84
+
85
+ All methods are prefixed with ```flow_```.
86
+
87
+ ## Helper lib
88
+
89
+ ### Spree::Flow::Gateway
90
+
91
+ Adapter for Spree, that allows using [Flow.io](https://www.flow.io) as payment gateway. Flow is PCI compliant payment processor.
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'FlowcommerceSpree'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.rdoc')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
20
+ load 'rails/tasks/engine.rake'
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+ task default: :test
data/SPREE_FLOW.md ADDED
@@ -0,0 +1,134 @@
1
+ # Flow, ActiveMerchant and Spree integration
2
+
3
+ Integration of Spree with Flow, how it is done.
4
+
5
+ I plan to be concise as possible, but cover all important topics.
6
+
7
+ ## Instalation
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:
25
+
26
+ ```
27
+ # ./config/initializers/flowcommerce_spree.rb
28
+
29
+ FlowcommerceSpree.configure do |c|
30
+ c.experience_associator = FlowcommerceSpree::ExperienceAssociator
31
+ end
32
+ ```
33
+
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
+ ## Things to take into account
40
+
41
+ ActiveMerchant is not supporting sessions and orders, natively. If one wants
42
+ to maintain sessions and orders in Flow, you have to do it outside the ActiveMerchant
43
+ terminology which focuses around purchases, voids and refunds.
44
+
45
+ Another thing to have in mind is that Spree can't work with ActiveMerchant directly, it has to have
46
+ an adapter. Adapter can be "stupid" and light, and can forward all the "heavy lifting" to ActiveMerchant gem
47
+ but it can also have all the logic localy.
48
+
49
+ In http://guides.spreecommerce.org/developer/payments.html at the bottom of the page Spree authors say
50
+
51
+ "better_spree_paypal_express and spree-adyen are good examples of standalone
52
+ custom gateways. No dependency on spree_gateway or activemerchant required."
53
+
54
+ Reading that we can see this is even considered good approach. For us, this is a possibility
55
+ but we consume ActiveMerchatFlow gem.
56
+
57
+ ## ActiveMerchant gem into more detail
58
+
59
+ https://github.com/flowcommerce/active_merchant
60
+
61
+ Sopporst stanard public ActiveMerchant actions which are
62
+ purchase, authorize, capture, void, store and refund.
63
+
64
+ It depends on following gems
65
+
66
+ * flowcommerce - api calls
67
+ * flow-reference - we use currency validations
68
+
69
+ It is not aware of Spree or any other shopping lib or framework.
70
+
71
+ ### ActiveMerchant::Flow supported actions in detail
72
+
73
+ * purchase - shortcut for authorize and then capture
74
+ * authorize - authorize the cc and funds.
75
+ * capture - capture the funds
76
+ * void - cancel the transaction
77
+ * store - store credit card (gets credit card flow token)
78
+ * refund - refund the funds
79
+
80
+ ## Spree Implementation in more detail
81
+
82
+ Not present as standalone gem, yet. I will do that once we agree on implementation details.
83
+
84
+ From product list to purchase, complete chain v1
85
+
86
+ 1. customer has to prepare data, migrate db and connect to Flow. In general
87
+ * create experiences in Flow console, add tiers, shipping methods, etc.
88
+ * add flow_data (jsonb) fields to this models
89
+ * Spree::Variant - we cache localized product prices
90
+ * Spree::Order - we cache flow order state details, shipping method
91
+ * create and sync product catalog via rake tasks
92
+ 1. now site users can browse prooducts and add them to cart.
93
+ 1. when user comes to shop, FlowSession is created
94
+ 1. once product is in cart
95
+ * spree order is created and linked to Experience that we get from FlowSession
96
+ * it is captured and synced with flow, realtime
97
+ * we do this all the time because we want to have 100% accurate prices.
98
+ Product prices that are shown in cart come directly from Flow API.
99
+ * in checkout, when customer address is added or shipping method defined,
100
+ all is synced with flow order.
101
+ * when order is complete, we trigger flow-cc-authorize or flow-cc-capture directly
102
+ on Spree::Order object instance. This is good because all gateway actions
103
+ are functions of the order object anyway.
104
+ * flow-cc-authorize or flow-cc-capture use ActiveMerchantFlow to execute this actions
105
+ * ActiveMerchantFlow included flow-reference gem
106
+
107
+ ## What can be better
108
+
109
+ We need a way to access the order in Rails. Access it after it is created in
110
+ controller but before it hits the render.
111
+ Current implementation is -> "overload" ApplicationController render
112
+ If we detect @spree_order object or debug flags, we react.
113
+
114
+ * good - elegant solution, all need code is in one file in few lines of code
115
+ * bad - somehow intrusive, we overload render, somw people will not like that.
116
+ * alternatives: gem that allows before_render bethod, call explicitly when needed
117
+
118
+ ## Aditional notes - view and frontend
119
+
120
+ I see many Spree merchant gems carry frontend code, js, coffe, views etc.
121
+ I thing that this is bad practise and that shop frontend has to be 100% customer code.
122
+
123
+ What I did not see but thing is great idea is to have custom light Flow admin present at
124
+
125
+ /admin/flow
126
+
127
+ that will ease the way of working with Flow. Code can be made to be Rails 4 and Rails 5 compatibile.
128
+ Part of that is allready done as can be seen here [Flow admin screenshot](https://i.imgur.com/FXbPrwK.png)
129
+
130
+ By default Flow Admin (on /admin/flow) is anybody that is Spree admin.
131
+
132
+ This way we provide good frontend info, some integration notes in realtime as opposed to running
133
+ rake tests to check for integrity of Flow integration.
134
+
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ CurrentZoneLoader.module_eval do
4
+ extend ActiveSupport::Concern
5
+
6
+ def flow_zone # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
7
+ return unless Spree::Zones::Product.active
8
+ .where("meta -> 'flow_data' ->> 'country' = ?",
9
+ ISO3166::Country[request_iso_code]&.alpha3).exists?
10
+
11
+ request_ip =
12
+ if Rails.env.production?
13
+ request.ip
14
+ else
15
+ Spree::Config[:debug_request_ip_address] || request.ip
16
+ # Germany ip: 85.214.132.117, Sweden ip: 62.20.0.196, Moldova ip: 89.41.76.29
17
+ end
18
+ flow_io_session = FlowcommerceSpree::Session
19
+ .new(ip: request_ip, visitor: visitor_id_for_flow_io)
20
+ # :create method will issue a request to flow.io. The experience, contained in the
21
+ # response, will be available in the session object - flow_io_session.experience
22
+ flow_io_session.create
23
+ zone = Spree::Zones::Product.active.find_by(name: flow_io_session.experience&.key&.titleize)
24
+ session['_f60_session'] = flow_io_session.id if zone
25
+ zone
26
+ end
27
+
28
+ # composes an unique vistor id for FlowcommerceSpree::Session model
29
+ def visitor_id_for_flow_io
30
+ guest_token = cookies.signed[:guest_token]
31
+ uid = if guest_token
32
+ Digest::SHA1.hexdigest(guest_token)
33
+ else
34
+ session_id = session[:session_id]
35
+ session_id ? Digest::SHA1.hexdigest(session_id) : Digest::SHA1.hexdigest(request.ip + request.user_agent)
36
+ end
37
+
38
+ "session-#{uid}"
39
+ 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
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlowcommerceSpree
4
+ class WebhooksController < ActionController::Base
5
+ respond_to :json
6
+
7
+ # forward all incoming requests to Flow WebhookService object
8
+ # /flow/event-target endpoint
9
+ def handle_flow_web_hook_event
10
+ webhook_result = WebhookService.process(params[:webhook])
11
+ result = {}
12
+ result[:error] = webhook_result.full_messages.join("\n") if webhook_result.errors.any?
13
+ rescue StandardError => e
14
+ result = { error: e.class.to_s, message: e.message, backtrace: e.backtrace }
15
+ ensure
16
+ response_status = if result[:error]
17
+ logger.info(result)
18
+ :unprocessable_entity
19
+ else
20
+ :ok
21
+ end
22
+ render json: result.except(:backtrace), status: response_status
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlowcommerceSpree
4
+ module ApplicationHelper
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Flow (2017)
4
+ # Enable this modifications if you want to display flow localized line item shipment price beside Spree default
5
+ # Example: https://i.imgur.com/7v2ix2G.png
6
+ module Spree
7
+ module Admin
8
+ OrdersHelper.module_eval do
9
+ # admin show line item total price
10
+ def line_item_shipment_price(line_item, quantity)
11
+ price = Spree::Money.new(line_item.price * quantity, currency: line_item.currency).to_s
12
+ price += " (#{@order.flow_line_item_price(line_item, quantity)})" if @order.flow_order
13
+ price.html_safe
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Core
5
+ module ControllerHelpers
6
+ # Spree::Core::ControllerHelpers::Order decorator to inject Flow.io Experience into the order, if such an
7
+ # Experience is present in the Order's zone
8
+ module FlowIoOrderHelperDecorator
9
+ private
10
+
11
+ def adjust_zone_and_ip
12
+ update_meta = @current_order.zone_id ? nil : true
13
+ @current_order.zone = current_zone
14
+
15
+ if @current_order.zone&.flow_io_active_experience? && @current_order.flow_io_experience_key.nil?
16
+ @current_order.flow_io_experience_from_zone
17
+ order_flow_io_session_id = @current_order.flow_data['session_id']
18
+ flow_io_session_id = session['_f60_session']
19
+ if order_flow_io_session_id.present? && flow_io_session_id.blank?
20
+ session['_f60_session'] = order_flow_io_session_id
21
+ elsif flow_io_session_id.present?
22
+ @current_order.flow_data['session_id'] = flow_io_session_id
23
+ end
24
+ update_meta = true
25
+ end
26
+
27
+ if @current_order.new_record?
28
+ @current_order.last_ip_address = ip_address
29
+ return @current_order.save
30
+ end
31
+
32
+ attrs_to_update = {}
33
+
34
+ # Update last_ip_address only for a new request_id
35
+ attrs_to_update = { last_ip_address: ip_address } if @request_id != request_id
36
+
37
+ # :meta is a jsonb column costly to update every time, especially with all the flow.io data, that's why
38
+ # here it is updated only if no zone_id there was inside :meta
39
+ attrs_to_update[:meta] = @current_order.meta.to_json if update_meta
40
+
41
+ @current_order.update_columns(attrs_to_update) if attrs_to_update.present?
42
+ attrs_to_update
43
+ end
44
+
45
+ def request_id
46
+ @request_id ||= env['action_dispatch.request_id']
47
+ end
48
+
49
+ ApplicationController.prepend(self) if ApplicationController.included_modules.exclude?(self)
50
+ end
51
+ end
52
+ end
53
+ end