workarea-flow_io 1.2.1

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 (272) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintignore +2 -0
  3. data/.eslintrc.json +37 -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 +90 -0
  8. data/.gitignore +21 -0
  9. data/.rubocop.yml +2 -0
  10. data/.ruby-version +1 -0
  11. data/.stylelintrc.json +12 -0
  12. data/CHANGELOG.md +200 -0
  13. data/Gemfile +19 -0
  14. data/LICENSE +52 -0
  15. data/README.md +200 -0
  16. data/Rakefile +59 -0
  17. data/app/assets/javascripts/workarea/storefront/flow_io/adapters/flow_io_adapter.js +61 -0
  18. data/app/assets/javascripts/workarea/storefront/flow_io/configuration.js.erb +10 -0
  19. data/app/assets/javascripts/workarea/storefront/flow_io/flow.js +91 -0
  20. data/app/assets/stylesheets/flow_io/storefront/country_picker.scss +189 -0
  21. data/app/controllers/workarea/admin/application_controller.decorator +5 -0
  22. data/app/controllers/workarea/admin/catalog_categories_controller.decorator +9 -0
  23. data/app/controllers/workarea/admin/flow_imports_controller.rb +9 -0
  24. data/app/controllers/workarea/admin/orders_controller.decorator +6 -0
  25. data/app/controllers/workarea/admin/pricing_skus_controller.decorator +7 -0
  26. data/app/controllers/workarea/admin/search_settings_controller.decorator +27 -0
  27. data/app/controllers/workarea/storefront/application_controller.decorator +80 -0
  28. data/app/controllers/workarea/storefront/checkouts_controller.decorator +38 -0
  29. data/app/controllers/workarea/storefront/flow_io_webhook_controller.rb +49 -0
  30. data/app/controllers/workarea/storefront/recent_views_controller.decorator +15 -0
  31. data/app/controllers/workarea/storefront/searches_controller.decorator +11 -0
  32. data/app/helpers/workarea/admin/flow_helper.rb +13 -0
  33. data/app/helpers/workarea/storefront/flow_analytics_helper.rb +23 -0
  34. data/app/helpers/workarea/storefront/flow_content_helper.rb +21 -0
  35. data/app/middleware/workarea/flow_io/session_middleware.rb +68 -0
  36. data/app/models/workarea/address.decorator +12 -0
  37. data/app/models/workarea/catalog/category.decorator +8 -0
  38. data/app/models/workarea/checkout.decorator +26 -0
  39. data/app/models/workarea/flow_io/experience_geo.rb +18 -0
  40. data/app/models/workarea/flow_io/experience_summary.rb +15 -0
  41. data/app/models/workarea/flow_io/import.rb +31 -0
  42. data/app/models/workarea/flow_io/imported_item.rb +124 -0
  43. data/app/models/workarea/flow_io/local_item.rb +28 -0
  44. data/app/models/workarea/flow_io/localized_price.rb +30 -0
  45. data/app/models/workarea/flow_io/price.rb +12 -0
  46. data/app/models/workarea/flow_io/price_with_base.rb +7 -0
  47. data/app/models/workarea/flow_io/webhook/shared_secret.rb +12 -0
  48. data/app/models/workarea/flow_price_adjustment_set.rb +80 -0
  49. data/app/models/workarea/fulfillment.decorator +63 -0
  50. data/app/models/workarea/order.decorator +39 -0
  51. data/app/models/workarea/order/item.decorator +43 -0
  52. data/app/models/workarea/payment.decorator +11 -0
  53. data/app/models/workarea/payment/authorize/flow_payment.rb +48 -0
  54. data/app/models/workarea/payment/capture/flow_payment.rb +35 -0
  55. data/app/models/workarea/payment/flow_payment_data.rb +25 -0
  56. data/app/models/workarea/payment/flow_payment_operation.rb +20 -0
  57. data/app/models/workarea/payment/purchase/flow_payment.rb +44 -0
  58. data/app/models/workarea/payment/refund/flow_payment.rb +42 -0
  59. data/app/models/workarea/payment/store_flow_credit_card.rb +34 -0
  60. data/app/models/workarea/payment/tender.decorator +8 -0
  61. data/app/models/workarea/payment/tender/flow_payment.rb +15 -0
  62. data/app/models/workarea/payment/transaction.decorator +12 -0
  63. data/app/models/workarea/pricing/calculators/flow_localization_calculator.rb +30 -0
  64. data/app/models/workarea/pricing/calculators/item_calculator.decorator +39 -0
  65. data/app/models/workarea/pricing/collection.decorator +113 -0
  66. data/app/models/workarea/pricing/order_totals.decorator +53 -0
  67. data/app/models/workarea/pricing/price.decorator +17 -0
  68. data/app/models/workarea/pricing/price_distributor.decorator +51 -0
  69. data/app/models/workarea/pricing/request.decorator +17 -0
  70. data/app/models/workarea/pricing/shipping_totals.decorator +24 -0
  71. data/app/models/workarea/pricing/sku.decorator +46 -0
  72. data/app/models/workarea/search/settings.decorator +8 -0
  73. data/app/models/workarea/search/storefront/product.decorator +25 -0
  74. data/app/models/workarea/shipping.decorator +28 -0
  75. data/app/queries/workarea/order_metrics.decorator +23 -0
  76. data/app/queries/workarea/search/product_search.decorator +14 -0
  77. data/app/queries/workarea/search/storefront_search/response.decorator +40 -0
  78. data/app/services/workarea/flow_io/checkout.rb +242 -0
  79. data/app/services/workarea/flow_io/checkout_token_form.rb +36 -0
  80. data/app/services/workarea/flow_io/countries.rb +14 -0
  81. data/app/services/workarea/flow_io/detailed_shipping_notification_form.rb +84 -0
  82. data/app/services/workarea/flow_io/experiences.rb +24 -0
  83. data/app/services/workarea/flow_io/fulfillment_cancellation_form.rb +40 -0
  84. data/app/services/workarea/flow_io/item.rb +122 -0
  85. data/app/services/workarea/flow_io/item_importer.rb +108 -0
  86. data/app/services/workarea/flow_io/line_item_form.rb +72 -0
  87. data/app/services/workarea/flow_io/order_put_form.rb +62 -0
  88. data/app/services/workarea/flow_io/price_applier.rb +81 -0
  89. data/app/services/workarea/flow_io/price_applier/item_applier.rb +157 -0
  90. data/app/services/workarea/flow_io/routing_contraints.rb +10 -0
  91. data/app/services/workarea/flow_io/session.rb +90 -0
  92. data/app/services/workarea/flow_io/webhook.rb +28 -0
  93. data/app/services/workarea/flow_io/webhook/experience_deleted_v2.rb +9 -0
  94. data/app/services/workarea/flow_io/webhook/experience_upserted_v2.rb +9 -0
  95. data/app/services/workarea/flow_io/webhook/order_upserted_v2.rb +36 -0
  96. data/app/services/workarea/flow_io/webhook_request_signature.rb +19 -0
  97. data/app/view_models/workarea/admin/flow_imports_view_model.rb +36 -0
  98. data/app/view_models/workarea/storefront/cart_view_model.decorator +27 -0
  99. data/app/view_models/workarea/storefront/content_blocks/category_summary_view_model.decorator +11 -0
  100. data/app/view_models/workarea/storefront/content_blocks/product_insights_view_model.decorator +11 -0
  101. data/app/view_models/workarea/storefront/content_blocks/product_list_view_model.decorator +13 -0
  102. data/app/view_models/workarea/storefront/order_item_view_model.decorator +35 -0
  103. data/app/view_models/workarea/storefront/order_view_model.decorator +51 -0
  104. data/app/view_models/workarea/storefront/product_templates/option_set_view_model.decorator +20 -0
  105. data/app/view_models/workarea/storefront/product_templates/package_view_model.decorator +14 -0
  106. data/app/view_models/workarea/storefront/product_view_model.decorator +15 -0
  107. data/app/view_models/workarea/storefront/product_view_model/cache_key.decorator +7 -0
  108. data/app/view_models/workarea/storefront/recommendations_view_model.decorator +20 -0
  109. data/app/view_models/workarea/storefront/user_activity_view_model.decorator +18 -0
  110. data/app/views/workarea/admin/catalog_categories/edit.html.haml +85 -0
  111. data/app/views/workarea/admin/facets/_price_inputs.html.haml +50 -0
  112. data/app/views/workarea/admin/flow_imports/index.html.haml +44 -0
  113. data/app/views/workarea/admin/orders/_flow.html.haml +22 -0
  114. data/app/views/workarea/admin/orders/_flow_aux_navigation.html.haml +2 -0
  115. data/app/views/workarea/admin/orders/flow.html.haml +109 -0
  116. data/app/views/workarea/admin/orders/tenders/_flow_payment.html.haml +3 -0
  117. data/app/views/workarea/admin/pricing_skus/_cards.html.haml +83 -0
  118. data/app/views/workarea/admin/pricing_skus/flow.html.haml +60 -0
  119. data/app/views/workarea/admin/search_settings/show.html.haml +55 -0
  120. data/app/views/workarea/admin/shared/_flow_imports_link.html.haml +1 -0
  121. data/app/views/workarea/storefront/_flow_io_country_picker.html.haml +2 -0
  122. data/app/views/workarea/storefront/_flow_io_country_picker_javascript.html.haml +1 -0
  123. data/app/views/workarea/storefront/order_mailer/tenders/_flow_payment.html.haml +2 -0
  124. data/app/views/workarea/storefront/order_mailer/tenders/_flow_payment.text.erb +1 -0
  125. data/app/views/workarea/storefront/orders/tenders/_flow_payment.html.haml +3 -0
  126. data/app/views/workarea/storefront/products/_pricing.html.haml +41 -0
  127. data/app/workers/workarea/flow_io/delete_items.rb +30 -0
  128. data/app/workers/workarea/flow_io/fetch_import.rb +34 -0
  129. data/app/workers/workarea/flow_io/fulfillment_cancellation.rb +14 -0
  130. data/app/workers/workarea/flow_io/item_exporter.rb +47 -0
  131. data/app/workers/workarea/flow_io/process_import.rb +28 -0
  132. data/app/workers/workarea/flow_io/shipping_notifications.rb +13 -0
  133. data/bin/rails +25 -0
  134. data/config/initializers/appends.rb +39 -0
  135. data/config/initializers/freedom_patches.rb +23 -0
  136. data/config/initializers/middleware.rb +11 -0
  137. data/config/initializers/payment_proxy.rb +5 -0
  138. data/config/initializers/rack_attack.rb +15 -0
  139. data/config/initializers/scheduled_jobs.rb +9 -0
  140. data/config/initializers/workarea.rb +101 -0
  141. data/config/initializers/workarea_i18n.rb +11 -0
  142. data/config/locales/en.yml +72 -0
  143. data/config/routes.rb +21 -0
  144. data/lib/active_merchant/billing/bogus_flow_gateway.rb +16 -0
  145. data/lib/active_merchant/billing/flow_gateway.rb +48 -0
  146. data/lib/tasks/flow_io.rake +117 -0
  147. data/lib/workarea/flow_io.rb +73 -0
  148. data/lib/workarea/flow_io/bogus_client.rb +57 -0
  149. data/lib/workarea/flow_io/bogus_client/checkout_tokens.rb +25 -0
  150. data/lib/workarea/flow_io/bogus_client/experiences.rb +152 -0
  151. data/lib/workarea/flow_io/bogus_client/fulfillments.rb +9 -0
  152. data/lib/workarea/flow_io/bogus_client/items.rb +11 -0
  153. data/lib/workarea/flow_io/bogus_client/orders.rb +499 -0
  154. data/lib/workarea/flow_io/bogus_client/organizations.rb +42 -0
  155. data/lib/workarea/flow_io/bogus_client/proxy_client.rb +29 -0
  156. data/lib/workarea/flow_io/bogus_client/sessions.rb +115 -0
  157. data/lib/workarea/flow_io/bogus_client/shipping_notifications.rb +10 -0
  158. data/lib/workarea/flow_io/bogus_client/webhook_settings.rb +11 -0
  159. data/lib/workarea/flow_io/bogus_client/webhooks.rb +11 -0
  160. data/lib/workarea/flow_io/controller_log_subscriber.rb +21 -0
  161. data/lib/workarea/flow_io/engine.rb +8 -0
  162. data/lib/workarea/flow_io/http_handler.rb +27 -0
  163. data/lib/workarea/flow_io/version.rb +5 -0
  164. data/lib/workarea/freedom_patches/flow_io.rb +53 -0
  165. data/package.json +9 -0
  166. data/script/admin_ci +9 -0
  167. data/script/ci +11 -0
  168. data/script/core_ci +9 -0
  169. data/script/plugins_ci +9 -0
  170. data/script/storefront_ci +9 -0
  171. data/test/dummy/.ruby-version +1 -0
  172. data/test/dummy/Rakefile +6 -0
  173. data/test/dummy/bin/bundle +3 -0
  174. data/test/dummy/bin/rails +4 -0
  175. data/test/dummy/bin/rake +4 -0
  176. data/test/dummy/bin/setup +28 -0
  177. data/test/dummy/bin/update +28 -0
  178. data/test/dummy/bin/yarn +11 -0
  179. data/test/dummy/config.ru +5 -0
  180. data/test/dummy/config/application.rb +32 -0
  181. data/test/dummy/config/boot.rb +5 -0
  182. data/test/dummy/config/cable.yml +10 -0
  183. data/test/dummy/config/environment.rb +5 -0
  184. data/test/dummy/config/environments/development.rb +52 -0
  185. data/test/dummy/config/environments/production.rb +88 -0
  186. data/test/dummy/config/environments/test.rb +45 -0
  187. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  188. data/test/dummy/config/initializers/assets.rb +14 -0
  189. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  190. data/test/dummy/config/initializers/content_security_policy.rb +25 -0
  191. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  192. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  193. data/test/dummy/config/initializers/inflections.rb +16 -0
  194. data/test/dummy/config/initializers/mime_types.rb +4 -0
  195. data/test/dummy/config/initializers/workarea.rb +5 -0
  196. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  197. data/test/dummy/config/locales/en.yml +33 -0
  198. data/test/dummy/config/puma.rb +34 -0
  199. data/test/dummy/config/routes.rb +5 -0
  200. data/test/dummy/config/secrets.yml +22 -0
  201. data/test/dummy/config/spring.rb +6 -0
  202. data/test/dummy/db/seeds.rb +2 -0
  203. data/test/dummy/log/.keep +0 -0
  204. data/test/dummy/package.json +5 -0
  205. data/test/factories/workarea/flow_io.rb +136 -0
  206. data/test/factories/workarea/flow_io/euro_order_upserted_payload.rb +581 -0
  207. data/test/fixtures/files/example.csv +14 -0
  208. data/test/integration/workarea/admin/flow_imports_integration_test.rb +20 -0
  209. data/test/integration/workarea/admin/flow_order_integration_test.rb +37 -0
  210. data/test/integration/workarea/admin/search_settings_integration_test.decorator +44 -0
  211. data/test/integration/workarea/flow_locale_integration_test.rb +34 -0
  212. data/test/integration/workarea/storefront/copying_guest_order_integration_test.decorator +113 -0
  213. data/test/integration/workarea/storefront/flow_io_order_redirect_test.rb +55 -0
  214. data/test/integration/workarea/storefront/flow_io_session_integration_test.rb +122 -0
  215. data/test/integration/workarea/storefront/flow_io_webhooks/order_integration_test.rb +750 -0
  216. data/test/integration/workarea/storefront/flow_webhook_rack_attack_integration_test.rb +54 -0
  217. data/test/integration/workarea/storefront/search_integration_test.decorator +51 -0
  218. data/test/javascripts/flow_spec.js +39 -0
  219. data/test/javascripts/spec_helper.js +3 -0
  220. data/test/models/workarea/address_test.decorator +20 -0
  221. data/test/models/workarea/checkout_test.decorator +20 -0
  222. data/test/models/workarea/flow_io/imported_item_test.rb +50 -0
  223. data/test/models/workarea/fulfillment_test.decorator +12 -0
  224. data/test/models/workarea/oms_fulfillment_test.decorator +14 -0
  225. data/test/models/workarea/order/item_test.decorator +46 -0
  226. data/test/models/workarea/order_test.decorator +16 -0
  227. data/test/models/workarea/payment/flow_payment_integration_test.rb +163 -0
  228. data/test/models/workarea/price_adjustment_set_flow_test.rb +8 -0
  229. data/test/models/workarea/pricing/calculators/flow_localization_calculator_test.rb +152 -0
  230. data/test/models/workarea/pricing/calculators/item_calculator_test.decorator +59 -0
  231. data/test/models/workarea/pricing/collection_test.decorator +140 -0
  232. data/test/models/workarea/pricing/order_totals_test.rb +247 -0
  233. data/test/models/workarea/pricing/price_distributor_test.decorator +21 -0
  234. data/test/models/workarea/pricing/sku_test.decorator +113 -0
  235. data/test/models/workarea/shipping_test.decorator +70 -0
  236. data/test/queries/workarea/flow_order_metrics_test.rb +104 -0
  237. data/test/services/workarea/commit_shipments_test.decorator +14 -0
  238. data/test/services/workarea/flow_io/checkout_test.rb +43 -0
  239. data/test/services/workarea/flow_io/detailed_shipping_notification_form_test.rb +145 -0
  240. data/test/services/workarea/flow_io/experiences_test.rb +14 -0
  241. data/test/services/workarea/flow_io/fulfillment_cancellation_form_test.rb +46 -0
  242. data/test/services/workarea/flow_io/item_importer_test.rb +357 -0
  243. data/test/services/workarea/flow_io/item_test.rb +72 -0
  244. data/test/services/workarea/flow_io/line_item_form_test.rb +34 -0
  245. data/test/services/workarea/flow_io/order_put_form_test.rb +48 -0
  246. data/test/services/workarea/flow_io/price_applier_test.rb +916 -0
  247. data/test/support/flow_fixtures.rb +1362 -0
  248. data/test/support/webhook_integration_test.rb +43 -0
  249. data/test/support/workarea/flow_bogus_client_support.rb +18 -0
  250. data/test/support/workarea/flow_io_vcr_config.rb +22 -0
  251. data/test/system/workarea/admin/search_fulfillment_system_test.decorator +25 -0
  252. data/test/system/workarea/storefront/analytics_system_test.decorator +28 -0
  253. data/test/system/workarea/storefront/flow_cart_recommendations_system_test.rb +70 -0
  254. data/test/system/workarea/storefront/users_flow_orders_system_test.rb +25 -0
  255. data/test/teaspoon_env.rb +6 -0
  256. data/test/test_helper.rb +27 -0
  257. data/test/vcr_cassettes/payment/flow/auth_capture.yml +188 -0
  258. data/test/vcr_cassettes/payment/flow/auth_capture_refund.yml +249 -0
  259. data/test/vcr_cassettes/payment/flow/auth_void.yml +188 -0
  260. data/test/vcr_cassettes/payment/flow/purchase_refund.yml +249 -0
  261. data/test/vcr_cassettes/payment/flow/store_auth.yml +127 -0
  262. data/test/vcr_cassettes/payment/flow/store_purchase.yml +188 -0
  263. data/test/view_models/workarea/storefront/cart_view_model_test.decorator +19 -0
  264. data/test/view_models/workarea/storefront/order_item_view_model_test.decorator +24 -0
  265. data/test/view_models/workarea/storefront/order_view_model_test.decorator +41 -0
  266. data/test/view_models/workarea/storefront/package_view_model_test.decorator +11 -0
  267. data/test/workers/workarea/flow_io/delete_items_test.rb +37 -0
  268. data/test/workers/workarea/flow_io/fetch_import_test.rb +41 -0
  269. data/test/workers/workarea/flow_io/item_exporter_test.rb +47 -0
  270. data/test/workers/workarea/flow_io/process_import_test.rb +25 -0
  271. data/workarea-flow_io.gemspec +20 -0
  272. metadata +375 -0
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ decorate Storefront::SearchesController, with: :flow_io do
3
+ decorated { before_action :add_flow_experience }
4
+
5
+ private
6
+
7
+ def add_flow_experience
8
+ params.merge!(experience: flow_experience)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ module Admin
3
+ module FlowHelper
4
+ def default_currency
5
+ Money.default_currency
6
+ end
7
+
8
+ def flow_currencies
9
+ FlowIo::Experiences.all_currencies.map { |currency| Money::Currency.new(currency) }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Workarea
2
+ module Storefront
3
+ module FlowAnalyticsHelper
4
+ def product_analytics_data(product)
5
+ super.merge(
6
+ currency_code: product.sell_min_price&.currency&.iso_code,
7
+ ).compact
8
+ end
9
+
10
+ def order_item_analytics_data(item)
11
+ super.merge(currency_code: item.current_unit_price.currency.iso_code)
12
+ end
13
+
14
+ def order_analytics_data(order)
15
+ super.merge(
16
+ total_price_currency_code: order.total_price.currency.iso_code,
17
+ shipping_total_currency_code: order.shipping_total.currency.iso_code,
18
+ tax_total_currency_code: order.tax_total.currency.iso_code
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ module Storefront
3
+ module FlowContentHelper
4
+ def render_content_blocks(blocks)
5
+ if current_user.try(:admin?)
6
+ render_content_blocks_without_cache(blocks)
7
+ else
8
+ cache_key = [
9
+ flow_experience&.key,
10
+ blocks.map(&:cache_key).join('/')
11
+ ].compact.join('/')
12
+
13
+ Rails.cache.fetch(
14
+ cache_key,
15
+ expires_in: Workarea.config.cache_expirations.render_content_blocks
16
+ ) { render_content_blocks_without_cache(blocks) }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,68 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class SessionMiddleware
4
+ include Rack::Utils
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ flow_session = FlowIo::Session.new(env)
12
+
13
+ env['Vary'] = 'X-Requested-With, X-Flash-Messages, X-Flow-Experience'
14
+ begin
15
+ env['HTTP_X_FLOW_EXPERIENCE'] = flow_session.experience&.key
16
+ env['flow.io.experience'] = flow_session.experience
17
+ env['flow.io.country'] = flow_session.flow_country
18
+ rescue => error
19
+ capture_exception error
20
+ return @app.call env
21
+ end
22
+
23
+ status, headers, body = @app.call env
24
+
25
+ if %r{text/html}.match? headers['Content-Type']
26
+ if flow_session.set_f60_session_cookie?
27
+ set_cookie_header!(headers, "_f60_session", {
28
+ value: flow_session.id,
29
+ path: "/",
30
+ expires: 1.year.from_now
31
+ })
32
+ end
33
+
34
+ if flow_session.set_flow_experience_cookie?
35
+ experince_cookie_value =
36
+ if flow_session.experience.present?
37
+ JSON.generate(flow_session.experience.to_hash)
38
+ else
39
+ ""
40
+ end
41
+
42
+ set_cookie_header!(headers, "flow_experience", {
43
+ value: experince_cookie_value,
44
+ path: "/",
45
+ expires: 1.year.from_now
46
+ })
47
+ end
48
+
49
+ if flow_session.set_flow_country_cookie?
50
+ set_cookie_header!(headers, "flow_country", flow_session.flow_country)
51
+ end
52
+ end
53
+
54
+ [status, headers, body]
55
+ end
56
+
57
+ private
58
+
59
+ def capture_exception(exception)
60
+ if defined?(::Raven)
61
+ Raven.capture_exception(exception)
62
+ else
63
+ Rails.logger.warn "Error in FlowIo::SessionMiddleware: #{exception}"
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,12 @@
1
+ module Workarea
2
+ decorate Address, with: :flow_io do
3
+ decorated do
4
+ field :flow, type: Boolean, default: false
5
+ end
6
+
7
+ def region_presence
8
+ return if flow?
9
+ super
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ decorate Catalog::Category, with: :flow_io do
3
+ decorated do
4
+ # price facets for currencies other than the default transacting currency
5
+ field :currency_localized_facets, type: Hash, default: {}
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ module Workarea
2
+ decorate Checkout, with: :flow_io do
3
+ decorated do
4
+ delegate :experience, to: :order
5
+ end
6
+
7
+ def shippings
8
+ super.tap do |workarea_shippings|
9
+ next unless experience.present?
10
+
11
+ workarea_shippings.each do |shipping|
12
+ shipping.build_experience experience.as_document
13
+ end
14
+ end
15
+ end
16
+
17
+ def shippable?
18
+ # WA does not have all the available shipping methods
19
+ # that flow supports, So by default the order will be
20
+ # shippable from flow
21
+ return true if order.flow?
22
+ super
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,18 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class ExperienceGeo
4
+ include ApplicationDocument
5
+
6
+ field :key, type: String
7
+ field :name, type: String
8
+ field :region, type: Hash
9
+ field :country, type: Country
10
+ field :currency, type: String
11
+ field :language, type: String
12
+ field :measurement_system, type: String
13
+
14
+ embedded_in :experienceable, polymorphic: true
15
+ validates_presence_of :key, :name
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class ExperienceSummary
4
+ include ApplicationDocument
5
+
6
+ field :key, type: String
7
+ field :name, type: String
8
+ field :country, type: Country
9
+ field :currency, type: String
10
+ field :language, type: String
11
+
12
+ validates_presence_of :key, :name
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module Workarea
2
+ module FlowIo
3
+ # Where import CSV is stored, as well as some other metadata
4
+ # surrounding the processing of the aformentioned data.
5
+ class Import
6
+ include ApplicationDocument
7
+ extend Dragonfly::Model
8
+
9
+ field :name, type: String
10
+ field :file_uid, type: String
11
+ field :started_at, type: Time
12
+ field :completed_at, type: Time
13
+
14
+ dragonfly_accessor :file, app: :workarea
15
+
16
+ delegate :path, to: :file, prefix: true
17
+
18
+ validates :name, presence: true, uniqueness: true
19
+
20
+ index({ name: 1 }, { unique: true, background: true })
21
+ index(
22
+ { created_at: 1 },
23
+ { expire_after_seconds: Workarea.config.data_file_operation_ttl.seconds.to_i }
24
+ )
25
+
26
+ def complete?
27
+ completed_at.present?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,124 @@
1
+ module Workarea
2
+ module FlowIo
3
+ # Represents a local item imported by the CSV importer.
4
+ class ImportedItem
5
+ attr_reader :params, :experiences
6
+
7
+ def initialize(row, experiences)
8
+ # HACK needed to parse params with keys like
9
+ # `parent[child][param]`, since that's what they come in
10
+ # as from the CSV.
11
+ @params = Rack::Utils.default_query_parser
12
+ .parse_nested_query(row.to_h.to_query)
13
+ .deep_symbolize_keys
14
+ @experiences = experiences
15
+ end
16
+
17
+ def self.process(row, experiences)
18
+ new(row, experiences).tap(&:save!)
19
+ end
20
+
21
+ def save!
22
+ # We don't care about world experience since it it needs to be converted
23
+ # by Flows javascript on the storefront
24
+ return if experience_key.match?(/world/i)
25
+
26
+ Sidekiq::Callbacks.disable(Workarea::FlowIo::ItemExporter) do
27
+ if local_item.present?
28
+ local_item.update_attributes(local_item_attributes)
29
+ else
30
+ sku.flow_io_local_items.create!(local_item_attributes)
31
+ end
32
+
33
+ sku.save!
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def experience_key
40
+ params[:experience][:key]
41
+ end
42
+
43
+ def experience
44
+ @experience ||=
45
+ begin
46
+ exp = experiences.detect { |e| e.key == experience_key }
47
+
48
+ ExperienceSummary.new(
49
+ key: experience_key,
50
+ name: exp.name,
51
+ country: exp.country,
52
+ currency: Country.find_country_by_alpha3(exp.currency),
53
+ language: exp.language
54
+ )
55
+ end
56
+ end
57
+
58
+ def sku
59
+ @sku ||= Pricing::Sku.find_or_create_by!(_id: params[:item][:number])
60
+ end
61
+
62
+ def local_item
63
+ @local_item ||= sku.flow_io_local_items
64
+ .detect { |li| li.experience.key == experience.key }
65
+ end
66
+
67
+ def local_item_attributes
68
+ {
69
+ experience: experience,
70
+ prices: prices
71
+ }.merge(msrp)
72
+ end
73
+
74
+ def pricing_attributes
75
+ params[:prices][:price_attributes]
76
+ end
77
+
78
+ def msrp
79
+ return {} unless msrp_attributes = pricing_attributes[:msrp]
80
+
81
+ {
82
+ msrp: {
83
+ price: Money.from_amount(msrp_attributes[:amount].to_f, msrp_attributes[:currency]),
84
+ label: msrp_attributes[:label],
85
+ base_currency: {
86
+ price: Money.from_amount(msrp_attributes[:base][:amount].to_f, msrp_attributes[:base][:currency]),
87
+ label: msrp_attributes[:base][:label]
88
+ }
89
+ }
90
+ }
91
+ end
92
+
93
+ def prices
94
+ regular = pricing_attributes[:regular_price]
95
+ sale = pricing_attributes[:sale_price]
96
+
97
+ price = {
98
+ min_quantity: 1,
99
+ regular: {
100
+ price: Money.from_amount(regular[:amount].to_f, regular[:currency]),
101
+ label: regular[:label],
102
+ base_currency: {
103
+ price: Money.from_amount(regular[:base][:amount].to_f, regular[:base][:currency]),
104
+ label: regular[:base][:label]
105
+ }
106
+ }
107
+ }
108
+
109
+ if sale.present?
110
+ price[:sale] = {
111
+ price: Money.from_amount(sale[:amount].to_f, sale[:currency]),
112
+ label: sale[:label],
113
+ base_currency: {
114
+ price: Money.from_amount(sale[:base][:amount].to_f, sale[:base][:currency]),
115
+ label: sale[:base][:label]
116
+ }
117
+ }
118
+ end
119
+
120
+ [price]
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,28 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class LocalItem
4
+ include ApplicationDocument
5
+
6
+ field :included_levies, type: Hash, default: {}
7
+
8
+ embedded_in :sku, class_name: "Workarea::Pricing::Sku"
9
+
10
+ embeds_one :experience, class_name: "Workarea::FlowIo::ExperienceSummary"
11
+ embeds_one :msrp, class_name: "Workarea::FlowIo::PriceWithBase"
12
+ embeds_many :prices, class_name: "Workarea::FlowIo::LocalizedPrice"
13
+
14
+ validates_presence_of :experience
15
+
16
+ # Creates a Pricing::Price from this local item
17
+ # used in Pricing::Sku#find_price
18
+ #
19
+ # @return [Pricing::Price]
20
+ #
21
+ def to_price(quantity = 1)
22
+ prices.sort_by(&:min_quantity).reverse.detect do |localized_price|
23
+ quantity >= localized_price.min_quantity
24
+ end&.to_price || Workarea::Pricing::Price.new(regular: 0.to_m(experience.currency))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class LocalizedPrice
4
+ include ApplicationDocument
5
+
6
+ field :min_quantity, type: Integer, default: 1
7
+
8
+ embeds_one :regular, class_name: "Workarea::FlowIo::PriceWithBase"
9
+ embeds_one :sale, class_name: "Workarea::FlowIo::PriceWithBase"
10
+
11
+ embedded_in :local_item, class_name: "Workarea::FlowIo::LocalItem"
12
+
13
+ validates_presence_of :regular
14
+
15
+ # Creates a Pricing::Price from this local item
16
+ # used in Pricing::Sku#find_price
17
+ #
18
+ # @return [Workarea::Pricing::Price]
19
+ #
20
+ def to_price
21
+ Workarea::Pricing::Price.new(
22
+ sku: self.local_item.sku.clone, # clone the sku so this price isn't added to #prices on real record
23
+ min_quantity: min_quantity,
24
+ regular: regular.price,
25
+ sale: sale&.price
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end