workarea-kount 3.3.0

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 (163) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.eslintrc +24 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  5. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  7. data/.github/workflows/ci.yml +58 -0
  8. data/.gitignore +14 -0
  9. data/.rubocop.yml +2 -0
  10. data/CHANGELOG.md +212 -0
  11. data/CODE_OF_CONDUCT.md +3 -0
  12. data/CONTRIBUTING.md +3 -0
  13. data/Gemfile +17 -0
  14. data/LICENSE.md +3 -0
  15. data/README.md +98 -0
  16. data/Rakefile +53 -0
  17. data/app/controllers/workarea/admin/orders_controller.decorator +5 -0
  18. data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +11 -0
  19. data/app/controllers/workarea/storefront/kount_controller.rb +19 -0
  20. data/app/controllers/workarea/storefront/kount_orders_controller.rb +40 -0
  21. data/app/lib/active_shipping/rate_estimate.decorator +10 -0
  22. data/app/mailers/workarea/storefront/order_mailer.decorator +14 -0
  23. data/app/models/workarea/checkout.decorator +37 -0
  24. data/app/models/workarea/checkout/fraud/kount_analyzer.rb +71 -0
  25. data/app/models/workarea/kount/ens_event.rb +13 -0
  26. data/app/models/workarea/kount/order.rb +14 -0
  27. data/app/models/workarea/order.decorator +62 -0
  28. data/app/models/workarea/order/fraud_decision.decorator +9 -0
  29. data/app/models/workarea/order/item.decorator +8 -0
  30. data/app/models/workarea/order/status/review.rb +13 -0
  31. data/app/models/workarea/payment/credit_card.decorator +13 -0
  32. data/app/models/workarea/payment/payment.decorator +11 -0
  33. data/app/models/workarea/payment/status/kount_declined.rb +13 -0
  34. data/app/models/workarea/payment/status/kount_review.rb +13 -0
  35. data/app/models/workarea/payment/tender/credit_card.decorator +10 -0
  36. data/app/models/workarea/search/admin.decorator +12 -0
  37. data/app/models/workarea/search/admin/order.decorator +7 -0
  38. data/app/models/workarea/shipping/rate_lookup.decorator +26 -0
  39. data/app/models/workarea/shipping/service.decorator +9 -0
  40. data/app/models/workarea/shipping/service_selection.decorator +7 -0
  41. data/app/models/workarea/shipping_option.decorator +27 -0
  42. data/app/services/workarea/kount/cancel_order_under_review.rb +28 -0
  43. data/app/services/workarea/kount/event.rb +43 -0
  44. data/app/services/workarea/kount/event/dmc_event.rb +9 -0
  45. data/app/services/workarea/kount/event/risk_change_event.rb +21 -0
  46. data/app/services/workarea/kount/event/special_alert_event.rb +21 -0
  47. data/app/services/workarea/kount/event/workflow_event.rb +25 -0
  48. data/app/services/workarea/kount/event_batch.rb +37 -0
  49. data/app/services/workarea/kount/order_fraud_update_service.rb +42 -0
  50. data/app/services/workarea/kount/ris_inquiry.rb +120 -0
  51. data/app/services/workarea/kount/ris_inquiry/product.rb +53 -0
  52. data/app/services/workarea/kount/ris_request.rb +84 -0
  53. data/app/services/workarea/kount/ris_update.rb +39 -0
  54. data/app/view_models/workarea/admin/order_view_model.decorator +35 -0
  55. data/app/view_models/workarea/storefront/order_view_model.decorator +11 -0
  56. data/app/views/workarea/admin/orders/_kount.html.haml +28 -0
  57. data/app/views/workarea/admin/orders/kount.html.haml +46 -0
  58. data/app/views/workarea/storefront/checkouts/_kount_data_collector.html.haml +4 -0
  59. data/app/views/workarea/storefront/order_mailer/hold_denial.html.haml +14 -0
  60. data/app/workers/workarea/kount/process_review_order.rb +75 -0
  61. data/app/workers/workarea/kount/update_ris_inquiry.rb +31 -0
  62. data/bin/rails +18 -0
  63. data/config/initializers/appends.rb +11 -0
  64. data/config/initializers/workarea.rb +26 -0
  65. data/config/locales/en.yml +26 -0
  66. data/config/routes.rb +14 -0
  67. data/doc/Kount Technical Specification Guide 5.5.5.pdf +0 -0
  68. data/lib/workarea/kount.rb +87 -0
  69. data/lib/workarea/kount/address.rb +39 -0
  70. data/lib/workarea/kount/bogus_gateway.rb +415 -0
  71. data/lib/workarea/kount/engine.rb +8 -0
  72. data/lib/workarea/kount/errors.rb +2 -0
  73. data/lib/workarea/kount/gateway.rb +50 -0
  74. data/lib/workarea/kount/mappings.rb +195 -0
  75. data/lib/workarea/kount/payment_types.rb +50 -0
  76. data/lib/workarea/kount/response.rb +141 -0
  77. data/lib/workarea/kount/security_mash.rb +79 -0
  78. data/lib/workarea/kount/user_defined_fields.rb +16 -0
  79. data/lib/workarea/kount/version.rb +5 -0
  80. data/lib/workarea/mailer_previews/storefront/order_mailer_preview.rb +10 -0
  81. data/test/dummy/Rakefile +6 -0
  82. data/test/dummy/app/assets/config/manifest.js +4 -0
  83. data/test/dummy/app/assets/images/.keep +0 -0
  84. data/test/dummy/app/assets/javascripts/application.js +13 -0
  85. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  86. data/test/dummy/app/controllers/application_controller.rb +3 -0
  87. data/test/dummy/app/controllers/concerns/.keep +0 -0
  88. data/test/dummy/app/helpers/application_helper.rb +2 -0
  89. data/test/dummy/app/jobs/application_job.rb +2 -0
  90. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  91. data/test/dummy/app/models/concerns/.keep +0 -0
  92. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  93. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  94. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  95. data/test/dummy/bin/bundle +3 -0
  96. data/test/dummy/bin/rails +4 -0
  97. data/test/dummy/bin/rake +4 -0
  98. data/test/dummy/bin/setup +34 -0
  99. data/test/dummy/bin/update +29 -0
  100. data/test/dummy/config.ru +5 -0
  101. data/test/dummy/config/application.rb +23 -0
  102. data/test/dummy/config/boot.rb +5 -0
  103. data/test/dummy/config/cable.yml +9 -0
  104. data/test/dummy/config/environment.rb +5 -0
  105. data/test/dummy/config/environments/development.rb +56 -0
  106. data/test/dummy/config/environments/production.rb +86 -0
  107. data/test/dummy/config/environments/test.rb +44 -0
  108. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  109. data/test/dummy/config/initializers/assets.rb +11 -0
  110. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  111. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  112. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  113. data/test/dummy/config/initializers/inflections.rb +16 -0
  114. data/test/dummy/config/initializers/mime_types.rb +4 -0
  115. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  116. data/test/dummy/config/initializers/session_store.rb +3 -0
  117. data/test/dummy/config/initializers/workarea.rb +5 -0
  118. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  119. data/test/dummy/config/locales/en.yml +23 -0
  120. data/test/dummy/config/puma.rb +47 -0
  121. data/test/dummy/config/routes.rb +6 -0
  122. data/test/dummy/config/secrets.yml +22 -0
  123. data/test/dummy/config/spring.rb +6 -0
  124. data/test/dummy/db/seeds.rb +2 -0
  125. data/test/dummy/lib/assets/.keep +0 -0
  126. data/test/dummy/log/.keep +0 -0
  127. data/test/dummy/public/404.html +67 -0
  128. data/test/dummy/public/422.html +67 -0
  129. data/test/dummy/public/500.html +66 -0
  130. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  131. data/test/dummy/public/apple-touch-icon.png +0 -0
  132. data/test/dummy/public/favicon.ico +0 -0
  133. data/test/factories/kount.rb +164 -0
  134. data/test/integration/workarea/api/admin/payment_transactions_integration_test.decorator +29 -0
  135. data/test/integration/workarea/kount_moneris_integration_test.rb +37 -0
  136. data/test/integration/workarea/storefront/kount_integration_test.rb +37 -0
  137. data/test/integration/workarea/storefront/kount_orders_integration_test.rb +89 -0
  138. data/test/lib/workarea/kount/response_test.rb +95 -0
  139. data/test/lib/workarea/kount/security_mash_test.rb +62 -0
  140. data/test/models/workarea/checkout/fraud/kount_analyzer_test.rb +44 -0
  141. data/test/models/workarea/checkout_test.decorator +22 -0
  142. data/test/models/workarea/order/queries_test.decorator +28 -0
  143. data/test/models/workarea/order_test.decorator +25 -0
  144. data/test/models/workarea/payment/payment_test.rb +106 -0
  145. data/test/models/workarea/payment/saved_credit_card_test.rb +24 -0
  146. data/test/models/workarea/payment_test.decorator +54 -0
  147. data/test/models/workarea/shipping_option_test.rb +29 -0
  148. data/test/services/workarea/kount/event_batch_test.rb +95 -0
  149. data/test/services/workarea/kount/event_test.rb +51 -0
  150. data/test/services/workarea/kount/order_fraud_update_service_test.rb +48 -0
  151. data/test/support/workarea/kount_api_config.rb +27 -0
  152. data/test/system/workarea/kount_system_test.rb +72 -0
  153. data/test/system/workarea/storefront/kount_guest_checkout_system_test.rb +32 -0
  154. data/test/system/workarea/storefront/kount_logged_in_checkout_system_test.rb +102 -0
  155. data/test/test_helper.rb +16 -0
  156. data/test/vcr_cassettes/kount/basic_fraud_test.yml +43 -0
  157. data/test/vcr_cassettes/kount/integration/moneris_new_credit_card.yml +84 -0
  158. data/test/vcr_cassettes/kount/integration/moneris_saved_credit_card.yml +84 -0
  159. data/test/vcr_cassettes/kount/order_fraud_update.yml +82 -0
  160. data/test/workers/workarea/kount/clean_orders_test.rb +40 -0
  161. data/test/workers/workarea/kount/process_review_order_test.rb +100 -0
  162. data/workarea-kount.gemspec +17 -0
  163. metadata +238 -0
@@ -0,0 +1,3 @@
1
+ View this plugin's license here:
2
+
3
+ <https://github.com/workarea-commerce/workarea/blob/master/LICENSE.md>
@@ -0,0 +1,98 @@
1
+ # Workarea Kount
2
+
3
+ Kount plugin for the Workarea platform.
4
+
5
+ ## Kount Response Codes
6
+
7
+ Kount's Risk Inquiry Services will return one of three values.
8
+
9
+ Approved - the order is not suspected as fraud
10
+
11
+ Decline - the order is fraud
12
+
13
+ Hold for manager review - the order is suspected fraud
14
+
15
+ ## Kount Order Flow
16
+
17
+ ### In Checkout
18
+
19
+ The Kount plugin sends the credit card and paypal orders to Kount before payment
20
+ is captured. Based on the response from Kount different actions will be taken.
21
+
22
+ #### Approved - The order is not fraud
23
+
24
+ The order is placed.
25
+
26
+ #### Decline - The order is fraud
27
+
28
+ An error is shown to the customer and redirected back to the payment step.
29
+
30
+ #### Hold for manager review - the order is suspected fraud
31
+
32
+ The credit card is tokenized and inventory is captured but the payment is not
33
+ authorized/purchased. The customer is shown the order confirmation as if the
34
+ order is placed. A Kount admin user needs to use approve or decline the order
35
+ via the Kount admin.
36
+
37
+ The Kount Event Notificaion System (ENS) will post the data back to Workarea.
38
+
39
+ If the admin declines the order in Kount, the order is canceled and the customer
40
+ recieves a cancelation email.
41
+
42
+ If the admin approves the order, the payment is attemped to be captured. If the
43
+ payment captures successfully the order is placed. If the payment fails
44
+ authorization/purchase, the order is canceled and the customer recives a
45
+ cancelation email.
46
+
47
+ ## Configuration
48
+
49
+ Add values for `merchant_id`, `version`, `key`, and `ksalt` to your application secrets
50
+
51
+ ```yaml
52
+ kount:
53
+ merchant_id:
54
+ version:
55
+ key:
56
+ ksalt:
57
+ ens_username: username for basic auth for ENS
58
+ ens_password: password for basic auth for ENS
59
+ kount_site: <site name for ENS>
60
+ ```
61
+
62
+ ### Event Notification System Configuration
63
+
64
+ The Kount ENS requires configuration in Workarea to match configuration in Kount.
65
+ If the ENS is not configured properly, Kount review decisions will not be
66
+ received by Workarea.
67
+
68
+ Workarea uses basic auth credentials `ens_username:ens_password` to authenticate
69
+ requests from the Kount ENS. If your application is behind basic_auth (e.g. in
70
+ staging or QA) you should configure these credentials to match your basic auth
71
+ credentials for the environment. If your application is not behind basic auth
72
+ these credentials can be anything you want, as long as they are secure.
73
+
74
+ #### Kount Site
75
+
76
+ The `kount_site` configuration is used by kount ENS to determine which endpoint
77
+ events should be sent to. If no `kount_site` is provided the DEFAULT site will
78
+ be used. `kount_site` can be used to configure different ENS endpoints for
79
+ testing inQA and Staging, or for multi-site implementations.
80
+
81
+ #### Configure ENS in Kount
82
+
83
+ In the Kount admin navigate to: Fraud Control -> Websites -> Add Website
84
+
85
+ The ENS Api URL should look like `https://ENS_USERNAME:ENS_PASSWORD@WEBSITE_DOMAIN/kount_orders`
86
+
87
+ Example: `https://kount:aksjei8243d8@www.example.com/kount_orders`
88
+
89
+ ## Workarea Platform Documentation
90
+
91
+ See [http://developer.workarea.com](http://developer.workarea.com) for Workarea
92
+ platform documentation.
93
+
94
+ ## Copyright & Licensing
95
+
96
+ Copyright WebLinc 2018. All rights reserved.
97
+
98
+ For licensing, contact sales@weblinc.com.
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ require 'rdoc/task'
9
+
10
+ RDoc::Task.new(:rdoc) do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = 'Tasker'
13
+ rdoc.options << '--line-numbers'
14
+ rdoc.rdoc_files.include('README.md')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+
18
+ APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
19
+ load 'rails/tasks/engine.rake'
20
+ load 'rails/tasks/statistics.rake'
21
+ load 'workarea/changelog.rake'
22
+
23
+ require 'rake/testtask'
24
+
25
+ Rake::TestTask.new(:test) do |t|
26
+ t.libs << 'lib'
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
33
+
34
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
35
+ require 'workarea/kount/version'
36
+
37
+ desc "Release version #{Workarea::Kount::VERSION} of the gem"
38
+ task :release do
39
+ host = "https://#{ENV['BUNDLE_GEMS__WORKAREA__COM']}@gems.workarea.com"
40
+
41
+ Rake::Task['workarea:changelog'].execute
42
+ system 'git add CHANGELOG.md'
43
+ system 'git commit -m "Update CHANGELOG"'
44
+ system 'git push origin HEAD'
45
+
46
+ system "git tag -a v#{Workarea::Kount::VERSION} -m 'Tagging #{Workarea::Kount::VERSION}'"
47
+ system 'git push --tags'
48
+
49
+ system 'gem build workarea-kount.gemspec'
50
+ system "gem push workarea-kount-#{Workarea::Kount::VERSION}.gem"
51
+ system "gem push workarea-kount-#{Workarea::Kount::VERSION}.gem --host #{host}"
52
+ system "rm workarea-kount-#{Workarea::Kount::VERSION}.gem"
53
+ end
@@ -0,0 +1,5 @@
1
+ module Workarea
2
+ decorate Admin::OrdersController, with: :kount do
3
+ def kount; end
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ decorate Storefront::Checkout::PlaceOrderController, with: :kount do
3
+ def try_place_order
4
+ if current_checkout.place_order || current_checkout.handle_kount_review
5
+ completed_place_order
6
+ else
7
+ incomplete_place_order
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Workarea
2
+ module Storefront
3
+ class KountController < Workarea::Storefront::ApplicationController
4
+ def data_collector
5
+ current_order.update_attributes(kount_session_id: kount_session_id)
6
+
7
+ params = { merchant_id: Workarea::Kount.merchant_id, s: kount_session_id }
8
+
9
+ redirect_to "#{Workarea::Kount.data_collector_url}logo.htm?#{params.to_query}", status: 302
10
+ end
11
+
12
+ private
13
+
14
+ def kount_session_id
15
+ @kount_session_id ||= "#{current_order.id}#{Time.now.to_i}R#{rand(10000..99999)}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ module Workarea
2
+ module Storefront
3
+ class KountOrdersController < ApplicationController
4
+ skip_before_action :verify_authenticity_token, only: [:bulk]
5
+ before_action :authenticate
6
+
7
+ def bulk
8
+ event_batch = Kount::EventBatch.new(request.raw_post)
9
+
10
+ if event_batch.valid?
11
+ event_batch.process!
12
+ successful_response
13
+ else
14
+ unsuccessful_response
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def authenticate
21
+ authenticated = authenticate_with_http_basic do |username, password|
22
+ Kount.credentials[:ens_username].present? &&
23
+ Kount.credentials[:ens_password].present? &&
24
+ username == Kount.credentials[:ens_username] &&
25
+ password == Kount.credentials[:ens_password]
26
+ end
27
+
28
+ unsuccessful_response unless authenticated
29
+ end
30
+
31
+ def successful_response
32
+ render json: { status: 200 }
33
+ end
34
+
35
+ def unsuccessful_response
36
+ head :bad_request
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveShipping
2
+ decorate RateEstimate, with: :kount do
3
+ decorated { attr_accessor :kount_code }
4
+
5
+ def initialize(origin, destination, carrier, service_name, options = {})
6
+ super
7
+ self.kount_code = options[:kount_code]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ decorate Storefront::OrderMailer, with: :kount do
3
+ def hold_denial(order_id)
4
+ order = Order.find(order_id)
5
+ @order = Storefront::OrderViewModel.new(order)
6
+ @recommendations = Storefront::EmailRecommendationsViewModel.wrap(order)
7
+
8
+ mail(
9
+ to: @order.email,
10
+ subject: t('workarea.storefront.email.hold_denial.subject', order_id: @order.id)
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ module Workarea
2
+ decorate Checkout, with: :kount do
3
+ def handle_kount_review
4
+ return false unless order.under_review?
5
+ return false unless complete?
6
+ return false unless shippable?
7
+ return false unless payable?
8
+
9
+ inventory.purchase
10
+ return false unless inventory.captured?
11
+
12
+ return true unless payment.uses_credit_card?
13
+ store_credit_card
14
+ end
15
+
16
+ def handle_kount_approved
17
+ unless payment_collection.purchase
18
+ captured_inventory&.rollback
19
+ return false
20
+ end
21
+
22
+ result = order.place
23
+ place_order_side_effects if result
24
+ result
25
+ end
26
+
27
+ private
28
+
29
+ def captured_inventory
30
+ @captured_inventory ||= Inventory::Transaction.captured_for_order(order.id)
31
+ end
32
+
33
+ def store_credit_card
34
+ Payment::StoreCreditCard.new(payment.credit_card).save!
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Workarea
4
+ class Checkout
5
+ module Fraud
6
+ class KountAnalyzer < Analyzer
7
+ # This is the `:mode` value used in the RIS Inquiry request to
8
+ # Kount. It tells Kount that this is a new order, and not an
9
+ # update to an existing order as used in the updater service
10
+ # class.
11
+ #
12
+ # @return [String]
13
+ MODE_Q = 'Q'
14
+
15
+ delegate :gateway, to: Workarea::Kount
16
+ delegate :kount_mode, :kount_request_user_defined_fields, to: :checkout
17
+ delegate :decision, to: :kount_response
18
+
19
+ # Tell Kount about the order and record its response.
20
+ #
21
+ # @return [Workarea::Order::FraudDecision]
22
+ def make_decision
23
+ kount_order.update_attributes!(response: kount_response)
24
+
25
+ Workarea::Order::FraudDecision.new(
26
+ decision: decision,
27
+ message: message
28
+ )
29
+ end
30
+
31
+ # Data for this Order from Kount.
32
+ #
33
+ # @return [Workarea::Kount::Order]
34
+ def kount_order
35
+ @kount_order ||= Workarea::Kount::Order.find_or_initialize_by(id: order.id)
36
+ end
37
+
38
+ private
39
+
40
+ # Build the RIS inquiry request.
41
+ #
42
+ # @private
43
+ # @return [Hash]
44
+ def inquiry
45
+ Workarea::Kount::RisInquiry.new(
46
+ order: order,
47
+ payment: payment,
48
+ shippings: shippings,
49
+ mode: MODE_Q
50
+ ).to_h
51
+ end
52
+
53
+ # Response for the Kount RIS inquiry request.
54
+ #
55
+ # @private
56
+ # @return [Workarea::Kount::Response]
57
+ def kount_response
58
+ @kount_response ||= gateway.call(inquiry)
59
+ end
60
+
61
+ # Translated message for the Kount decision.
62
+ #
63
+ # @private
64
+ # @return [String]
65
+ def message
66
+ I18n.t(decision, scope: 'workarea.storefront.fraud.kount')
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ module Kount
3
+ class EnsEvent
4
+ include ApplicationDocument
5
+
6
+ field :xml, type: String
7
+
8
+ embedded_in :kount_order,
9
+ class_name: 'Workarea::Kount::Order',
10
+ inverse_of: :ens_events
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ module Kount
3
+ class Order
4
+ include ApplicationDocument
5
+
6
+ field :response, type: Workarea::Kount::Response
7
+ field :update_response, type: Workarea::Kount::Response
8
+
9
+ embeds_many :ens_events, class_name: 'Workarea::Kount::EnsEvent'
10
+
11
+ index(created_at: -1)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,62 @@
1
+ module Workarea
2
+ decorate Order, with: :kount do
3
+ decorated do
4
+ field :kount_session_id, type: String
5
+ field :kount_decision, type: Symbol
6
+
7
+ scope :not_under_review, -> { where(:kount_decision.ne => :review) }
8
+
9
+ before_save :set_kount_decision, if: :fraud_decision?
10
+ end
11
+
12
+ class_methods do
13
+ # Query for orders which have expired in checkout, meaning they have been
14
+ # not been placed or updated for longer than the
15
+ # +Workarea.config.order_expiration_period+, but have started
16
+ # checkout. Contrast this with +Order.expired+, which does not
17
+ # factor in orders that have started checkout.
18
+ #
19
+ # Doesn't include orders under review or declined by kount
20
+ #
21
+ # @return [Mongoid::Criteria]
22
+ def expired_in_checkout
23
+ super.nin(kount_decision: [:review, :decline])
24
+ end
25
+
26
+ # Overriding method from core/models/order/queries.rb module
27
+ def need_reminding
28
+ super.where(kount_decision: nil)
29
+ end
30
+
31
+ # Find a current cart for a session. Returns a new order if one cannot be found.
32
+ #
33
+ # @param params [Hash]
34
+ # @return [Order]
35
+ #
36
+ def find_current(params = {})
37
+ if params[:id].present?
38
+ Order.not_placed.not_under_review.find(params[:id].to_s)
39
+ elsif params[:user_id].present?
40
+ Order.recently_updated.not_placed.not_under_review.find_by(params.slice(:user_id))
41
+ else
42
+ Order.new(user_id: params[:user_id])
43
+ end
44
+ rescue Mongoid::Errors::DocumentNotFound
45
+ Order.new(user_id: params[:user_id])
46
+ end
47
+ end
48
+
49
+ # Whether the FraudDecision#decision is `:review`.
50
+ def under_review?
51
+ !placed? && !canceled? && kount_decision == :review
52
+ end
53
+
54
+ def abandoned?
55
+ super && kount_decision.nil?
56
+ end
57
+
58
+ def set_kount_decision
59
+ self.kount_decision = fraud_decision.decision
60
+ end
61
+ end
62
+ end