workarea-flow_io 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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,30 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class DeleteItems
4
+ include Sidekiq::Worker
5
+ include Sidekiq::CallbacksWorker
6
+
7
+ sidekiq_options(
8
+ enqueue_on: {
9
+ Catalog::Product => :destroy,
10
+ Pricing::Sku => :destroy,
11
+ with: -> do
12
+ if self.class.name == "Workarea::Catalog::Product"
13
+ [self.skus]
14
+ else
15
+ [[id]]
16
+ end
17
+ end
18
+ }
19
+ )
20
+
21
+ def perform(skus)
22
+ client = FlowIo.client
23
+
24
+ skus.each do |sku|
25
+ client.items.delete_by_number(Workarea::FlowIo.organization_id, sku)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ module Workarea
2
+ module FlowIo
3
+ # Fetches new import CSVs from the FTP server, ignoring any that
4
+ # have already been processed.
5
+ class FetchImport
6
+ include Sidekiq::Worker
7
+
8
+ sidekiq_options lock: :until_executing
9
+
10
+ def perform
11
+ username = FlowIo.credentials[:ftp_username]
12
+ password = FlowIo.credentials[:ftp_password]
13
+ path = Pathname.new('flow').join('from-flow', 'export')
14
+
15
+ Net::SFTP.start(FlowIo::FTP_HOST, username, password: password) do |sftp|
16
+ sftp.dir.glob(path.to_s, '*.csv') do |entry|
17
+ Import.find_or_create_by!(name: entry.name) do |import|
18
+ import.file = Tempfile.new(entry.name).tap do |tmp|
19
+ begin
20
+ filepath = path.join(entry.name).to_s
21
+ csv = sftp.download!(filepath)
22
+
23
+ tmp.write(csv)
24
+ ensure
25
+ tmp.close
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class FulfillmentCancellation
4
+ include Sidekiq::Worker
5
+
6
+ def perform(id, canceled_items)
7
+ fulfillment_cancelation_form = FlowIo::FulfillmentCancellationForm.from(id: id, quantities: canceled_items)
8
+ order = Workarea::Order.find(id)
9
+
10
+ FlowIo.client.fulfillments.put_cancellations(FlowIo.organization_id, order.id, fulfillment_cancelation_form)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class ItemExporter
4
+ include Sidekiq::Worker
5
+ include Sidekiq::CallbacksWorker
6
+
7
+ sidekiq_options(
8
+ enqueue_on: {
9
+ Catalog::Product => :save,
10
+ Shipping::Sku => :save,
11
+ Pricing::Sku => :save,
12
+ Pricing::Price => :save,
13
+ with: -> { ItemExporter.perform_with(self) }
14
+ }
15
+ )
16
+
17
+ def self.perform_with(model)
18
+ case model.class.name
19
+ when "Workarea::Pricing::Price"
20
+ [model.sku.class.name, model.sku.id]
21
+ else
22
+ [model.class.name, model.id]
23
+ end
24
+ end
25
+
26
+ def perform(class_name, id)
27
+ product, skus =
28
+ if class_name == "Workarea::Catalog::Product"
29
+ prod = Catalog::Product.find(id)
30
+ [prod, prod.skus]
31
+ else
32
+ [Catalog::Product.find_by_sku(id), [id]]
33
+ end
34
+
35
+ return unless product.present?
36
+
37
+ client = FlowIo.client
38
+ organization_id = Workarea::FlowIo.organization_id
39
+
40
+ skus.each do |sku|
41
+ item = Workarea::FlowIo::Item.new(product, sku)
42
+ client.items.put_by_number(organization_id, sku, item.form)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
1
+ module Workarea
2
+ module FlowIo
3
+ # Reads the CSV stored in a `Workarea::FlowIo::Import`, and
4
+ # processes each row with `FlatFileItem.import`
5
+ class ProcessImport
6
+ include Sidekiq::Worker
7
+ include Sidekiq::CallbacksWorker
8
+
9
+ sidekiq_options \
10
+ lock: :until_executing,
11
+ enqueue_on: { Import => [:create] }
12
+
13
+ def perform(id)
14
+ import = Import.find(id)
15
+
16
+ import.update!(started_at: Time.current)
17
+
18
+ experiences = FlowIo.client.experiences.get(FlowIo.organization_id)
19
+
20
+ CSV.foreach(import.file_path, headers: true) do |row|
21
+ ImportedItem.process(row, experiences)
22
+ end
23
+
24
+ import.update!(completed_at: Time.current)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class ShippingNotifications
4
+ include Sidekiq::Worker
5
+
6
+ def perform(id, tracking_number)
7
+ shipping_notification_form = FlowIo::DetailedShippingNotificationForm.from(id: id, tracking_number: tracking_number)
8
+
9
+ FlowIo.client.shipping_notifications.post(FlowIo.organization_id, shipping_notification_form)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/workarea/flow_io/engine', __dir__)
7
+ APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
8
+
9
+ # Set up gems listed in the Gemfile.
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
11
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
12
+
13
+ require "rails"
14
+ # Pick the frameworks you want:
15
+ require "active_model/railtie"
16
+ require "active_job/railtie"
17
+ # require "active_record/railtie"
18
+ # require "active_storage/engine"
19
+ require "action_controller/railtie"
20
+ require "action_mailer/railtie"
21
+ require "action_view/railtie"
22
+ require "action_cable/engine"
23
+ require "sprockets/railtie"
24
+ require "rails/test_unit/railtie"
25
+ require 'rails/engine/commands'
@@ -0,0 +1,39 @@
1
+ Workarea.append_partials(
2
+ 'storefront.document_head',
3
+ 'workarea/storefront/flow_io_country_picker_javascript'
4
+ )
5
+
6
+ Workarea.append_javascripts(
7
+ 'storefront.modules',
8
+ 'workarea/storefront/flow_io/flow'
9
+ )
10
+
11
+ Workarea.append_javascripts(
12
+ 'storefront.config',
13
+ 'workarea/storefront/flow_io/configuration'
14
+ )
15
+
16
+ Workarea.append_partials(
17
+ 'storefront.footer_help',
18
+ 'workarea/storefront/flow_io_country_picker'
19
+ )
20
+
21
+ Workarea.append_partials(
22
+ 'admin.order_cards',
23
+ 'workarea/admin/orders/flow'
24
+ )
25
+
26
+ Workarea.append_partials(
27
+ 'admin.order_show_workflow_bar_left',
28
+ 'workarea/admin/orders/flow_aux_navigation'
29
+ )
30
+
31
+ Workarea::Plugin.append_stylesheets(
32
+ 'storefront.components',
33
+ 'flow_io/storefront/country_picker'
34
+ )
35
+
36
+ Workarea.append_partials(
37
+ 'admin.settings_menu',
38
+ 'workarea/admin/shared/flow_imports_link'
39
+ )
@@ -0,0 +1,23 @@
1
+ # This throws an *absurd* amount of deprecation warnings when running
2
+ # tests, making it pretty impossible to see what you're doing. It's due
3
+ # to the gem running in Ruby 2.6, which deprecated `BigDecimal.new` and
4
+ # replaced it with the `BigDecimal()` method. Every time
5
+ # `Helper.to_big_decimal` is called by the FlowCommerce gem, we get a
6
+ # big ol' deprecation warning in the console. This should silence those
7
+ # warnings until https://github.com/flowcommerce/ruby-sdk/issues/25 is
8
+ # resolved.
9
+ module Io
10
+ module Flow
11
+ module V0
12
+ module HttpClient
13
+ module Helper
14
+ def Helper.to_big_decimal(value)
15
+ return unless value.present?
16
+
17
+ BigDecimal(value.to_s)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ if Rails.application.config.action_dispatch.rack_cache
2
+ Rails.application.config.middleware.insert_before(
3
+ Rack::Cache,
4
+ Workarea::FlowIo::SessionMiddleware
5
+ )
6
+ else
7
+ Rails.application.config.middleware.insert_before(
8
+ Rack::Head,
9
+ Workarea::FlowIo::SessionMiddleware
10
+ )
11
+ end
@@ -0,0 +1,5 @@
1
+ if ENV['HTTP_PROXY'].present?
2
+ uri = URI.parse(ENV['HTTP_PROXY'])
3
+ ActiveMerchant::Billing::FlowGateway.proxy_address = uri.host
4
+ ActiveMerchant::Billing::FlowGateway.proxy_port = uri.port
5
+ end
@@ -0,0 +1,15 @@
1
+ class Rack::Attack
2
+ safelist('allow flow webhooks') do |req|
3
+ request_signature = req.env['HTTP_X_FLOW_SIGNATURE']
4
+
5
+ next false unless request_signature.present?
6
+
7
+ body = req.body.read
8
+ req.body.rewind
9
+
10
+ Workarea::FlowIo::WebhookRequestSignature.valid?(
11
+ request_signature: request_signature,
12
+ request_body: body
13
+ )
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ unless Workarea.config.skip_service_connections
2
+ if Workarea::FlowIo.credentials.key?(:ftp_username) && Workarea::FlowIo.credentials.key?(:ftp_password)
3
+ Sidekiq::Cron::Job.create(
4
+ name: 'Workarea::FlowIo::FetchImport',
5
+ klass: 'Workarea::FlowIo::FetchImport',
6
+ cron: "0 9 * * * #{Time.zone.tzinfo.identifier}"
7
+ )
8
+ end
9
+ end
@@ -0,0 +1,101 @@
1
+ Workarea.configure do |config|
2
+ config.cache_expirations.flow_io_country_cache = 1.hour
3
+
4
+ config.flow_io ||= ActiveSupport::Configurable::Configuration.new
5
+
6
+ # Enable JS integration for real-time price updates. Defaults to
7
+ # `false`.
8
+ config.flow_io.enable_javascript = false
9
+
10
+ # default payment action. FlowIO recomends purchase (auth/cap)
11
+ config.flow_io.default_payment_action = "purchase"
12
+
13
+ # default timeout on flow api calls
14
+ config.flow_io.default_timeout = 2
15
+
16
+ # hash of processor to image tags for flow
17
+ # see https://docs.flow.io/type/image-tag
18
+ config.flow_io.image_sizes = {
19
+ small_thumb: ["thumbnail"],
20
+ medium_thumb: ["checkout"],
21
+ }
22
+
23
+ # URI that flow checkouts will be redirected to.
24
+ # Exclude the trailing slash.
25
+ config.flow_io.checkout_uri = "https://checkout.flow.io"
26
+
27
+ config.tender_types.prepend(:flow_payment)
28
+
29
+ # The locale in which the content of the catalog is written.
30
+ config.flow_io.original_locale = "en_US"
31
+
32
+ config.flow_io.localization_attributes = [
33
+ {
34
+ key: 'regular_price',
35
+ options: {
36
+ required: true,
37
+ show_in_catalog: true,
38
+ show_in_harmonization: true
39
+ },
40
+ label: 'Regular Price',
41
+ intent: 'price',
42
+ type: 'decimal'
43
+ },
44
+ {
45
+ key: 'sale_price',
46
+ options: {
47
+ required: false,
48
+ show_in_catalog: true,
49
+ show_in_harmonization: true
50
+ },
51
+ label: 'Sale Price',
52
+ intent: 'price',
53
+ type: 'decimal'
54
+ },
55
+ {
56
+ key: 'msrp',
57
+ options: {
58
+ required: false,
59
+ show_in_catalog: true,
60
+ show_in_harmonization: true
61
+ },
62
+ label: 'MSRP',
63
+ intent: 'price',
64
+ type: 'decimal'
65
+ },
66
+ {
67
+ key: 'product_id',
68
+ options: {
69
+ required: true,
70
+ show_in_catalog: true,
71
+ show_in_harmonization: false
72
+ },
73
+ label: 'Product ID',
74
+ intent: 'product_id',
75
+ type: 'string'
76
+ },
77
+ {
78
+ key: 'fulfillment_method',
79
+ options: {
80
+ required: false,
81
+ show_in_catalog: true,
82
+ show_in_harmonization: false
83
+ },
84
+ label: 'Fulfillment Method',
85
+ intent: 'fulfillment_method',
86
+ type: 'String'
87
+ }
88
+ ]
89
+
90
+ config.pricing_calculators << "Workarea::Pricing::Calculators::FlowLocalizationCalculator"
91
+
92
+ config.flow_io.webhook_events = [
93
+ "order_upserted_v2",
94
+ "experience_deleted_v2",
95
+ "experience_upserted_v2"
96
+ ]
97
+
98
+ config.run_credit_card_refund_tests = true
99
+
100
+ config.exclude_from_search_results_breadcrumbs.push(:experience)
101
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ module I18n
3
+ module FlowIoConstraintOverride
4
+ def routes_constraint
5
+ Workarea::FlowIo::RoutingContraints.new
6
+ end
7
+ end
8
+
9
+ self.singleton_class.prepend FlowIoConstraintOverride
10
+ end
11
+ end
@@ -0,0 +1,72 @@
1
+ en:
2
+ workarea:
3
+ admin:
4
+ flow_imports:
5
+ errors:
6
+ error: Error
7
+ page_title: Errors for %{name} %{type}
8
+ dashboard_link: All Imports & Exports
9
+ title: Errors for %{name} %{type}
10
+ unknown_type: Unknown
11
+ table:
12
+ id_or_line: ID or Line Number
13
+ field: Field
14
+ message: Message
15
+ index:
16
+ dashboard_link: Settings dashboard
17
+ import: Import
18
+ info: Review details of imports from the last %{duration}
19
+ page_title: Flow Imports
20
+ showing: Showing %{count},
21
+ title: Flow Imports
22
+ view_imports: view imports
23
+ localized_prices:
24
+ label: Localized Prices
25
+ base: Base
26
+ base_tooltip: The price converted into the localized currency with rounding rules applied then converted back into the base currency.
27
+ localized: Localized
28
+ regular_base: Regular Base
29
+ regular_localized: Regular Localized
30
+ sale_localized: Sale Localized
31
+ sale_base: Sale Base
32
+ title: Localized Prices for %{sku}
33
+ orders:
34
+ view_flow_order: View Order in Flow Console
35
+ cards:
36
+ flow:
37
+ id: Flow Order ID
38
+ pending_import: Pending Import
39
+ flow_total_price: Flow Total Price
40
+ flow_tax_total: Flow Tax Total
41
+ attributes:
42
+ flow:
43
+ title: Flow
44
+ flow:
45
+ console: View in Flow Console
46
+ checkout:
47
+ title: Flow Checkout
48
+ customer: 'Customer:'
49
+ status: 'Status:'
50
+ items:
51
+ flow_pricing: "Flow Pricing (%{currency})"
52
+ pricing: "Base Pricing (%{currency})"
53
+ product: Product
54
+ quantity: Quantity
55
+ title: Items
56
+ title: "%{name} Details"
57
+ totals:
58
+ base_totals: Base Totals (%{currency})
59
+ flow_totals: "Flow Totals (%{currency})"
60
+ shipping: Shipping
61
+ subtotal: Subtotal
62
+ tax: Tax
63
+ title: Totals
64
+ total_price: Total Price
65
+ total_value: Total Value
66
+ pricing_skus:
67
+ cards:
68
+ localized_prices:
69
+ button: View Localized Prices
70
+ shared:
71
+ primary_nav:
72
+ flow_imports: Flow Imports