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,21 @@
1
+ Workarea::Storefront::Engine.routes.draw do
2
+ post :flow_webhook, as: :flow_io_webhook, controller: 'flow_io_webhook', action: 'event'
3
+ end
4
+
5
+ Workarea::Admin::Engine.routes.draw do
6
+ scope '(:locale)', constraints: Workarea::I18n.routes_constraint do
7
+ resources :flow_imports, only: :index
8
+
9
+ resources :orders, only: [] do
10
+ member do
11
+ get :flow
12
+ end
13
+ end
14
+
15
+ resources :pricing_skus, only: [] do
16
+ member do
17
+ get :flow
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ class BogusFlowGateway < BogusGateway
4
+ def store(paysource, options = {})
5
+ case normalize(paysource)
6
+ when /1$/
7
+ Response.new(true, SUCCESS_MESSAGE, { token: '1' }, test: true, authorization: AUTHORIZATION)
8
+ when /2$/
9
+ Response.new(false, FAILURE_MESSAGE, { token: nil, error: FAILURE_MESSAGE }, test: true, error_code: STANDARD_ERROR_CODE[:processing_error])
10
+ else
11
+ raise Error, error_message(paysource)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module FlowGatewayFixes
4
+ FORM_TYPES = [
5
+ :authorization_copy_form, :direct_authorization_form, :merchant_of_record_authorization_form,
6
+ :paypal_authorization_form, :redirect_authorization_form, :inline_authorization_form,
7
+ :card_authorization_form, :ach_authorization_form
8
+ ]
9
+
10
+ def purchase(credit_card, order_number, options = {})
11
+ response = authorize(credit_card, order_number, options)
12
+ capture(options[:amount], response.authorization, options)
13
+ end
14
+
15
+ # Create a new authorization.
16
+ # https://docs.flow.io/module/payment/resource/authorizations#post-organization-authorizations
17
+ def authorize(cc_or_token, order_number, opts = {})
18
+ unless opts[:currency]
19
+ return error_response('Currency is a required option')
20
+ end
21
+
22
+ unless opts[:discriminator]
23
+ return error_response 'Discriminator is not defined, please choose one [%s]' % FORM_TYPES.join(', ')
24
+ end
25
+
26
+ unless FORM_TYPES.include?(opts[:discriminator].to_sym)
27
+ return error_response 'Discriminator [%s] not found, please choose one [%s]' % [opts[:discriminator], FORM_TYPES.join(', ')]
28
+ end
29
+
30
+ body = {
31
+ amount: opts[:amount] || 0.0,
32
+ currency: opts[:currency],
33
+ discriminator: opts[:discriminator],
34
+ token: store(cc_or_token),
35
+ order_number: order_number
36
+ }
37
+
38
+ response = flow_instance.authorizations.post @flow_organization, body
39
+
40
+ # This is the only changed line, it just sets the response.id as Response#authorizzation
41
+ Response.new true, 'Flow authorize - Success', { response: response }, { authorization: response.id }
42
+ rescue => exception
43
+ error_response exception
44
+ end
45
+ end
46
+ FlowGateway.prepend FlowGatewayFixes
47
+ end
48
+ end
@@ -0,0 +1,117 @@
1
+ namespace :workarea do
2
+ namespace :flow_io do
3
+ desc 'export products'
4
+ task export_products: :environment do
5
+ puts "Exporting products..."
6
+ client = FlowCommerce.instance(token: Workarea::FlowIo.api_token)
7
+ organization_id = Workarea::FlowIo.organization_id
8
+
9
+ Workarea::Catalog::Product.all.each_by(100) do |product|
10
+ product.variants.each do |variant|
11
+ item = Workarea::FlowIo::Item.new(product, variant.sku)
12
+
13
+ puts "Adding #{variant.sku}"
14
+ client.items.put_by_number(organization_id, variant.sku, item.form)
15
+ end
16
+ end
17
+ end
18
+
19
+ desc 'create localization attributes'
20
+ task create_localization_attributes: :environment do
21
+ puts "Creating localization attributes..."
22
+ client = Workarea::FlowIo.client
23
+ organization_id = Workarea::FlowIo.organization_id
24
+
25
+ Workarea::FlowIo.config.localization_attributes.each do |localization_attribute|
26
+ puts "Adding attribute #{localization_attribute[:label]}"
27
+ client.attributes.put_by_key(
28
+ organization_id,
29
+ localization_attribute[:key],
30
+ localization_attribute
31
+ )
32
+ end
33
+ end
34
+
35
+ desc 'create webhooks'
36
+ task create_webhooks: :environment do
37
+ puts "Creating webhook shared secret..."
38
+ client = Workarea::FlowIo.client
39
+ secret = Workarea::FlowIo::Webhook::SharedSecret.first_or_create!
40
+ organization_id = Workarea::FlowIo.organization_id
41
+ client.webhook_settings.put(
42
+ organization_id,
43
+ secret: secret.token,
44
+ retry_max_attempts: 5,
45
+ retry_sleep_ms: 30,
46
+ sleep_ms: 30
47
+ )
48
+
49
+ puts "Creating webhooks..."
50
+ host = Workarea.config.host
51
+
52
+ webhook_url = Workarea::Storefront::Engine
53
+ .routes
54
+ .url_helpers
55
+ .flow_io_webhook_url(host: host, protocol: "https")
56
+
57
+ client.webhooks.post(
58
+ organization_id,
59
+ Io::Flow::V0::Models::WebhookForm.new(
60
+ events: Workarea::FlowIo.config.webhook_events,
61
+ url: webhook_url
62
+ )
63
+ )
64
+ end
65
+
66
+ desc 'Initialize Flow Plugin'
67
+ task install: :environment do
68
+ Rake::Task['workarea:flow_io:create_localization_attributes'].execute
69
+ Rake::Task['workarea:flow_io:create_webhooks'].execute
70
+ Rake::Task['workarea:flow_io:export_products'].execute
71
+ end
72
+
73
+ desc 'Delete items'
74
+ task delete_products: :environment do
75
+ client = FlowCommerce.instance(token: Workarea::FlowIo.api_token)
76
+ organization_id = Workarea::FlowIo.organization_id
77
+
78
+ Workarea::Catalog::Product.all.each_by(100) do |product|
79
+
80
+ product.variants.each do |variant|
81
+ client.items.delete_by_number(organization_id, variant.sku)
82
+ end
83
+ end
84
+ end
85
+
86
+ desc 'import local items'
87
+ task import_local_items: :environment do
88
+ organization = Workarea::FlowIo.organization_id
89
+ experiences = Workarea::FlowIo.client.experiences.get(organization)
90
+
91
+ experiences.each do |experience|
92
+ next unless experience.status.value == "active"
93
+
94
+ page_size = 100
95
+ offset = 0
96
+ items = []
97
+
98
+ while offset == 0 || items.length == 100
99
+ # show current list size
100
+ puts "\nGetting items: %s, rows %s - %s" % [experience.key, offset, offset + page_size]
101
+
102
+ items = Workarea::FlowIo.client.experiences.get_items organization, experience: experience.key, limit: page_size, offset: offset
103
+ offset += page_size
104
+
105
+ items.each do |item|
106
+ puts item.number
107
+ begin
108
+ Workarea::FlowIo::ItemImporter.perform!(item)
109
+ rescue Mongoid::Errors::DocumentNotFound => _error
110
+ puts "Missing pricing sku: #{item.number}"
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,73 @@
1
+ require 'flowcommerce'
2
+ require 'flowcommerce-activemerchant'
3
+ require 'active_merchant/billing/bogus_flow_gateway'
4
+ require 'active_merchant/billing/flow_gateway'
5
+ require 'net/sftp'
6
+
7
+ require 'workarea'
8
+ require 'workarea/storefront'
9
+ require 'workarea/admin'
10
+ require 'workarea/freedom_patches/flow_io'
11
+ require 'workarea/flow_io/controller_log_subscriber'
12
+
13
+ require 'workarea/flow_io/engine'
14
+ require 'workarea/flow_io/version'
15
+ require 'workarea/flow_io/http_handler'
16
+ require 'workarea/flow_io/bogus_client'
17
+
18
+ module Workarea
19
+ module FlowIo
20
+ FTP_HOST = 'ftp.flow.io'
21
+
22
+ def self.credentials
23
+ (Rails.application.secrets.flow_io || config.to_h).deep_symbolize_keys
24
+ end
25
+
26
+ def self.config
27
+ Workarea.config.flow_io
28
+ end
29
+
30
+ def self.api_token
31
+ credentials[:api_token]
32
+ end
33
+
34
+ def self.organization_id
35
+ credentials[:organization_id]
36
+ end
37
+
38
+ def self.image_sizes
39
+ config.image_sizes
40
+ end
41
+
42
+ def self.client(timeout: nil, open_timeout: nil, read_timeout: nil, logger: nil, **options)
43
+ timeout ||= config.default_timeout
44
+ read_timeout ||= timeout
45
+ open_timeout ||= timeout
46
+
47
+ if api_token.present?
48
+ FlowCommerce.instance(
49
+ token: Workarea::FlowIo.api_token,
50
+ http_handler: Workarea::FlowIo::HttpHandler.new(open_timeout: open_timeout, read_timeout: read_timeout, logger: logger, **options)
51
+ )
52
+ else
53
+ FlowIo::BogusClient.new
54
+ end
55
+ end
56
+
57
+ def self.webhook_shared_secret
58
+ Workarea::FlowIo::Webhook::SharedSecret.first.try(:token)
59
+ end
60
+
61
+ # Conditionally use the real gateway when secrets are present.
62
+ # Otherwise, use the bogus gateway.
63
+ #
64
+ # @return [ActiveMerchant::Billing::Gateway]
65
+ def self.gateway
66
+ if credentials.present?
67
+ ActiveMerchant::Billing::FlowGateway.new(api_key: Workarea::FlowIo.api_token, organization: Workarea::FlowIo.organization_id)
68
+ else
69
+ ActiveMerchant::Billing::BogusGateway.new
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,57 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class BogusClient
4
+ require 'workarea/flow_io/bogus_client/proxy_client'
5
+ require 'workarea/flow_io/bogus_client/checkout_tokens'
6
+ require 'workarea/flow_io/bogus_client/experiences'
7
+ require 'workarea/flow_io/bogus_client/fulfillments'
8
+ require 'workarea/flow_io/bogus_client/items'
9
+ require 'workarea/flow_io/bogus_client/orders'
10
+ require 'workarea/flow_io/bogus_client/organizations'
11
+ require 'workarea/flow_io/bogus_client/sessions'
12
+ require 'workarea/flow_io/bogus_client/shipping_notifications'
13
+ require 'workarea/flow_io/bogus_client/webhooks'
14
+ require 'workarea/flow_io/bogus_client/webhook_settings'
15
+
16
+ thread_cattr_accessor :requests, :store_requests
17
+
18
+
19
+ def self.reset_requests!
20
+ self.requests = Hash.new do |client_hash, client_class|
21
+ client_hash[client_class] = Hash.new do |method_hash, method_name|
22
+ method_hash[method_name] = []
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.total_request_count
28
+ self.requests.sum do |client, method_calls|
29
+ method_calls.sum { |_method, calls| calls.size }
30
+ end
31
+ end
32
+
33
+ self.store_requests = false
34
+ self.reset_requests!
35
+
36
+ def method_missing(method)
37
+ client_class = client(method)
38
+
39
+ if client_class
40
+ ProxyClient.new(method, client_class.new)
41
+ else
42
+ super
43
+ end
44
+ end
45
+
46
+ def respond_to_missing?(method, include_all = false)
47
+ client(method).present? || super
48
+ end
49
+
50
+ private
51
+
52
+ def client(client_name)
53
+ BogusClient.const_get(client_name.to_s.camelize) rescue nil
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class BogusClient
4
+ class CheckoutTokens
5
+ def post_checkout_and_tokens_by_organization(organization, checkout_token_form)
6
+ unless checkout_token_form.is_a? ::Io::Flow::V0::Models::CheckoutTokenForm
7
+ checkout_token_form = ::Io::Flow::V0::Models::CheckoutTokenForm.new(checkout_token_form)
8
+ end
9
+
10
+ ::Io::Flow::V0::Models::CheckoutToken.new(
11
+ id: SecureRandom.hex(20),
12
+ organization: { id: organization },
13
+ order: { number: checkout_token_form.order_number },
14
+ session: { id: checkout_token_form.session_id },
15
+ urls: {
16
+ continue_shopping: checkout_token_form.urls.continue_shopping
17
+ },
18
+ expires_at: 1.day.from_now.utc.iso8601(3),
19
+ checkout: { id: 'foo' }
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,152 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class BogusClient
4
+ class Experiences
5
+ def get(_organization_id)
6
+ [canada_experience, canada_2_experience, china_experience, europe_experience]
7
+ end
8
+
9
+ # @param organization_id [String]
10
+ # @param key [String]
11
+ #
12
+ def get_by_key(_organization_id, key)
13
+ case key
14
+ when "canada" then canada_experience
15
+ when "canada2" then canada_2_experience
16
+ when "china" then china_experience
17
+ when "europe" then europe_experience
18
+ else europe_experience
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def china_experience
25
+ ::Io::Flow::V0::Models::Experience.new(
26
+ "id" => "exp-5af698539a884d568dcdb950ed01521c",
27
+ "key" => "china",
28
+ "name" => "China",
29
+ "delivered_duty" => "paid",
30
+ "region" => { "id" => "chn" },
31
+ "country" => "CHN",
32
+ "currency" => "CNY",
33
+ "language" => "zh",
34
+ "measurement_system" => "metric",
35
+ "subcatalog" => {
36
+ "id" => "sca-c06ac78fe14c4618b025d922bb1b5594",
37
+ "discriminator" => "subcatalog_reference"
38
+ },
39
+ "position" => 2,
40
+ "settings" => {
41
+ "delivered_duty" => {
42
+ "default" => "paid",
43
+ "available" => ["paid", "unpaid"],
44
+ "display" => "all"
45
+ },
46
+ "pricing_settings" => {
47
+ "editable" => true,
48
+ "default_tax_display" => "included",
49
+ "default_duty_display" => "ignored"
50
+ },
51
+ "logistics_settings" => { "shipping_configuration" => { "key" => "001" } },
52
+ "checkout_settings" => {
53
+ "configuration" => { "id" => "chc-5dd603d15c9c4f5fbf8c96b98d66eeda" }
54
+ }
55
+ },
56
+ "status" => "active",
57
+ "discriminator" => "experience"
58
+ )
59
+ end
60
+
61
+ def europe_experience
62
+ ::Io::Flow::V0::Models::Experience.new(
63
+ "id" => "exp-5af698539a884d568dcdb950ed01521c",
64
+ "key" => "europe",
65
+ "name" => "Europe",
66
+ "delivered_duty" => "paid",
67
+ "region" => { "id" => "eur" },
68
+ "country" => "GBR",
69
+ "currency" => "EUR",
70
+ "language" => "eu",
71
+ "measurement_system" => "metric",
72
+ "subcatalog" => {
73
+ "id" => "sca-c06ac78fe14c4618b025d922bb1b5594",
74
+ "discriminator" => "subcatalog_reference"
75
+ },
76
+ "position" => 2,
77
+ "settings" => {
78
+ "delivered_duty" => {
79
+ "default" => "paid",
80
+ "available" => ["paid", "unpaid"],
81
+ "display" => "all"
82
+ },
83
+ "pricing_settings" => {
84
+ "editable" => true,
85
+ "default_tax_display" => "included",
86
+ "default_duty_display" => "ignored"
87
+ },
88
+ "logistics_settings" => { "shipping_configuration" => { "key" => "001" } },
89
+ "checkout_settings" => {
90
+ "configuration" => { "id" => "chc-5dd603d15c9c4f5fbf8c96b98d66eeda" }
91
+ }
92
+ },
93
+ "status" => "active",
94
+ "discriminator" => "experience"
95
+ )
96
+ end
97
+
98
+ def canada_experience
99
+ ::Io::Flow::V0::Models::Experience.new(
100
+ id: "exp-95889ba1ff4b449f8a3c0e0a7a4fb23b",
101
+ key: "canada",
102
+ name: "Canada",
103
+ delivered_duty: "paid",
104
+ region: { id: "can" },
105
+ country: "CAN",
106
+ currency: "CAD",
107
+ language: "en",
108
+ measurement_system: "metric",
109
+ subcatalog: { id: "sca-e866a54205db401ca0d5add025d4706b",
110
+ discriminator: "subcatalog_reference" },
111
+ position: 0,
112
+ settings: {
113
+ delivered_duty: {
114
+ default: "paid",
115
+ available: ["paid", "unpaid"],
116
+ display: "all"
117
+ }
118
+ },
119
+ status: "active",
120
+ discriminator: "experience"
121
+ )
122
+ end
123
+
124
+ def canada_2_experience
125
+ ::Io::Flow::V0::Models::Experience.new(
126
+ id: "exp-2d65a4a036e9480196bc36554b6a2b99",
127
+ key: "canada-2",
128
+ name: "Canada 2",
129
+ delivered_duty: "paid",
130
+ region: { id: "can" },
131
+ country: "CAN",
132
+ currency: "CAD",
133
+ language: "en",
134
+ measurement_system: "metric",
135
+ subcatalog: { id: "sca-fc951797454d4431a4d73efee56f3d67",
136
+ discriminator: "subcatalog_reference" },
137
+ position: 1,
138
+ settings: {
139
+ delivered_duty: {
140
+ default: "paid",
141
+ available: ["paid", "unpaid"],
142
+ display: "all"
143
+ }
144
+ },
145
+ status: "active",
146
+ discriminator: "experience"
147
+ )
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end