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,24 @@
1
+ module Workarea
2
+ decorate Pricing::ShippingTotals, with: :flow_io do
3
+ def total
4
+ super
5
+
6
+ return unless @shipping.experience.present?
7
+
8
+ set_flow_shipping_total
9
+ set_flow_tax_total
10
+ end
11
+
12
+ def flow_price_adjustments
13
+ @flow_price_adjustments ||= PriceAdjustmentSet.new(@shipping.flow_price_adjustments)
14
+ end
15
+
16
+ def set_flow_shipping_total
17
+ @shipping.flow_shipping_total = flow_price_adjustments.adjusting('shipping').sum
18
+ end
19
+
20
+ def set_flow_tax_total
21
+ @shipping.flow_tax_total = flow_price_adjustments.adjusting('tax').sum
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ module Workarea
2
+ decorate Pricing::Sku, with: :flow_io do
3
+ decorated do
4
+ embeds_many :flow_io_local_items, class_name: "Workarea::FlowIo::LocalItem"
5
+ end
6
+
7
+ # @return Money
8
+ def msrp_for_experience(experience)
9
+ local_item = flow_io_local_items.detect do |item|
10
+ item.experience.key == experience.key
11
+ end
12
+
13
+ local_item&.msrp&.price
14
+ end
15
+
16
+ # Find the price to sell at for a specific options.
17
+ #
18
+ # Takes options :quantity, :experience (::Io::Flow::V0::Models::ExperienceSummary || ::Io::Flow::V0::Models::ExperienceGeo)
19
+ #
20
+ # @param [Hash]
21
+ # @return [Pricing::Price]
22
+ #
23
+ def find_price(options = {})
24
+ return super unless options[:experience].present?
25
+
26
+ quantity = options[:quantity] || 1
27
+
28
+ local_item = flow_io_local_items.detect do |item|
29
+ item.experience.key == options[:experience].key
30
+ end
31
+
32
+ local_item&.to_price(quantity) ||
33
+ Pricing::Price.new(regular: 0.to_m(options[:experience].currency))
34
+ end
35
+
36
+ # @param Io::Flow::V0::Models::Item
37
+ def import_flow_item(flow_item)
38
+ local_item = flow_io_local_items.detect { |li| li.experience.key == flow_item.local.experience.key } ||
39
+ flow_io_local_items.new
40
+
41
+ local_item.update_from_flow_item(flow_item)
42
+
43
+ Sidekiq::Callbacks.disable(Workarea::FlowIo::ItemExporter) { save! }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ decorate Search::Settings, 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,25 @@
1
+ module Workarea
2
+ decorate Search::Storefront::Product, with: :flow_io do
3
+ def numeric
4
+ super.merge(localized_selling_prices)
5
+ end
6
+
7
+ def sorts
8
+ super.merge(localized_sort_prices)
9
+ end
10
+
11
+ private
12
+
13
+ def localized_sort_prices
14
+ pricing.localized_min_sell_prices.map do |experience_key, price|
15
+ ["price_#{experience_key}".systemize, price]
16
+ end.to_h
17
+ end
18
+
19
+ def localized_selling_prices
20
+ pricing.localized_selling_prices.map do |experience_key, prices|
21
+ ["price_#{experience_key}".systemize, prices.compact.uniq]
22
+ end.to_h
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module Workarea
2
+ decorate Shipping, with: :flow_io do
3
+ decorated do
4
+ field :flow_shipping_total, type: Money
5
+ field :flow_tax_total, type: Money
6
+ field :delivery_duty, type: String
7
+
8
+ embeds_one :experience, class_name: "Workarea::FlowIo::ExperienceGeo", as: :experienceable
9
+
10
+ embeds_many :flow_price_adjustments,
11
+ class_name: 'Workarea::PriceAdjustment',
12
+ extend: PriceAdjustmentExtension
13
+ end
14
+
15
+ def adjust_flow_pricing(options = {})
16
+ flow_price_adjustments.build(options)
17
+ end
18
+
19
+ # @param ::Io::Flow::V0::Models::DeliveryOption flow_shipping_method
20
+ def set_flow_shipping!(flow_shipping_method)
21
+ # clear the default shipping service.
22
+ self.shipping_service = nil
23
+ self.delivery_duty = flow_shipping_method.delivered_duty.value
24
+ self.build_shipping_service(name: flow_shipping_method.tier.name)
25
+ save!
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module Workarea
2
+ decorate OrderMetrics, with: :flow do
3
+ def discount_adjustments
4
+ return super unless order.flow?
5
+
6
+ PriceAdjustmentSet.new(all_price_adjustments.discounts.flat_map do |adjustment|
7
+ next adjustment unless adjustment.data['original_discounts'].present?
8
+
9
+ adjustment.data['original_discounts'].map do |adjustment_hash|
10
+ amount = Money.demongoize(adjustment_hash["amount"])
11
+
12
+ PriceAdjustment.new(
13
+ amount: amount,
14
+ quantity: adjustment_hash["quantity"],
15
+ data: {
16
+ "discount_id" => adjustment_hash["id"]
17
+ }
18
+ )
19
+ end
20
+ end)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ decorate Search::ProductSearch, with: :flow_io do
3
+ def selected_sort
4
+ return super unless params[:experience].present? &&
5
+ (params[:sort] == "price_asc" || params[:sort] == "price_desc")
6
+
7
+ if params[:sort] == "price_asc"
8
+ Sort.new(I18n.t('workarea.sorts.price_asc'), :price_asc, :"sorts.price_#{params[:experience].key.systemize}", :asc)
9
+ elsif params[:sort] == "price_desc"
10
+ sort.new(I18n.t('workarea.sorts.price_asc'), :price_asc, :"sorts.price_#{params[:experience].key.systemize}", :asc)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module Workarea
2
+ decorate Search::StorefrontSearch::Response, with: :flow_io do
3
+ decorated { attr_reader :experience }
4
+
5
+ def initialize(options = {})
6
+ @template = options.fetch(:template, 'show')
7
+ @message = options[:message]
8
+ @redirect = options[:redirect]
9
+
10
+ @params = options.fetch(:params, {})
11
+ @experience = @params[:experience]
12
+ @params[:terms_facets] = terms_facets
13
+ @params[:range_facets] = range_facets
14
+ @params[:experience] = options[:experience]
15
+ @original_params = @params.deep_dup
16
+
17
+ @customization = options[:customization]
18
+ @trace = []
19
+
20
+ reset!(@params)
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def default_range_facets
27
+ Search::Settings.current.range_facets
28
+ end
29
+
30
+ def range_facets
31
+ return default_range_facets unless experience.present?
32
+
33
+ localized_price_facets = Search::Settings.current.currency_localized_facets.fetch(experience.currency, {})
34
+
35
+ default_range_facets
36
+ .except("price")
37
+ .merge("price-#{experience.key}" => localized_price_facets)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,242 @@
1
+ module Workarea
2
+ module FlowIo
3
+ class Checkout
4
+ include Workarea::ApplicationHelper
5
+
6
+ attr_reader :order, :flow_order
7
+
8
+ # @param flow_order [::Io::Flow::V0::Models::Order]
9
+ # @param order [::Workarea::Order]
10
+ #
11
+ def initialize(flow_order, order)
12
+ @order = order
13
+ @flow_order = flow_order
14
+ end
15
+
16
+ def place_order
17
+ return false unless shipping.valid?
18
+ return false unless payment.valid?
19
+
20
+ inventory.purchase
21
+ return false unless inventory.captured?
22
+
23
+ result = order.place
24
+
25
+ if result
26
+ CreateFulfillment.new(order).perform
27
+ end
28
+
29
+ result
30
+ end
31
+
32
+ def build
33
+ order.update_attributes!(
34
+ experience: {
35
+ key: experience.key,
36
+ name: experience.name,
37
+ region: experience.region.to_hash,
38
+ country: experience.country,
39
+ currency: experience.currency,
40
+ language: experience.language,
41
+ measurement_system: experience.measurement_system
42
+ },
43
+ flow: true,
44
+ email: customer.email
45
+ )
46
+
47
+ FlowIo::PriceApplier.perform(order: pricing_order, flow_order: flow_order, shipping: pricing_shipping)
48
+ shipping.update_attributes!(pricing_shipping.as_document)
49
+
50
+ # set the shipping service.
51
+ shipping.set_flow_shipping!(flow_shipping_method)
52
+
53
+ # set the shipping and billing addresses
54
+ shipping.set_address(shipping_address_params(flow_order.destination))
55
+ payment.set_address(billing_address_params(flow_billing_address))
56
+
57
+ # use the flow payment processor for this order going forward.
58
+ # this allows for using a differnt payment processor for
59
+ # domestic orders
60
+ payment.operation_tender_type = 'FlowPayment'
61
+
62
+ # build a flow payment so we can refund later if needed.
63
+ flow_payments.each do |flow_payment|
64
+ payment.build_flow_payment(
65
+ details: flow_payment.to_hash,
66
+ payment_type: flow_payment.type,
67
+ description: flow_payment.description,
68
+ amount: Money.from_amount(flow_payment.total.base.amount, flow_payments.first.total.base.currency),
69
+ flow_amount: Money.from_amount(flow_payment.total.amount, flow_payments.first.total.currency)
70
+ )
71
+ end
72
+
73
+ # build a capture transaction for each
74
+ payment.tenders.each do |tender|
75
+
76
+ response = ActiveMerchant::Billing::Response.new(
77
+ true,
78
+ 'Flow Payment Transaction',
79
+ { response: tender.details }
80
+ )
81
+ transaction = payment.flow_payment.build_transaction(
82
+ tender_id: tender.id.to_s,
83
+ action: Workarea.config.flow_io.default_payment_action,
84
+ amount: tender.amount,
85
+ flow_amount: tender.flow_amount,
86
+ success: true,
87
+ response: response
88
+ )
89
+
90
+ transaction.save!
91
+ end
92
+
93
+ payment.save!
94
+
95
+ total_order
96
+
97
+ order.update_attributes!(pricing_order.as_document.reverse_merge(items: []))
98
+ end
99
+
100
+ private
101
+
102
+ def experience
103
+ @experience ||=
104
+ Workarea::FlowIo.client.experiences.get_by_key(
105
+ Workarea::FlowIo.organization_id,
106
+ flow_order.experience.key
107
+ )
108
+ end
109
+
110
+ # creates a clone of the persisted shipping
111
+ def pricing_shipping
112
+ @pricing_shipping ||=
113
+ begin
114
+ result = shipping.clone
115
+ result.id = shipping.id # Ensure this isn't persisted
116
+ result.reset_adjusted_shipping_pricing
117
+ result
118
+ end
119
+ end
120
+
121
+ def pricing_order
122
+ @pricing_order ||=
123
+ begin
124
+ result = @order.clone
125
+ result.id = @order.id # Ensure this isn't persisted
126
+ result.attributes = clone_order_attributes
127
+ result
128
+ end
129
+ end
130
+
131
+ def clone_order_attributes
132
+ @order.as_document.except('_id', 'id')
133
+ end
134
+
135
+ def shipping_address_params(address)
136
+ country = Country.find_country_by_alpha3(address.country)
137
+ region = get_region_by_name(country, address.province)
138
+
139
+ {
140
+ first_name: address.contact.name.first,
141
+ last_name: address.contact.name.last,
142
+ street: address.streets.first,
143
+ street_2: address.streets.second,
144
+ city: address.city,
145
+ region: region,
146
+ postal_code: address.postal,
147
+ country: country,
148
+ phone_number: address.contact.phone,
149
+ flow: true
150
+ }
151
+ end
152
+
153
+ def billing_address_params(address)
154
+ country = Country.find_country_by_alpha3(address.country)
155
+ region = get_region_by_name(country, address.province)
156
+ {
157
+ first_name: customer.name.first,
158
+ last_name: customer.name.last,
159
+ street: address.streets.first,
160
+ street_2: address.streets.second,
161
+ city: address.city,
162
+ region: region,
163
+ postal_code: address.postal,
164
+ country: country,
165
+ flow: true
166
+ }
167
+ end
168
+
169
+ def flow_payments
170
+ flow_order.payments
171
+ end
172
+
173
+ def customer
174
+ @customer ||= flow_order.customer
175
+ end
176
+
177
+ def get_region_by_name(country, region_name)
178
+ reg, _reg_struct = country.subdivisions.detect { |k, v| v.name == region_name }
179
+ reg
180
+ end
181
+
182
+ def flow_shipping_method_ids
183
+ @flow_shipping_method_ids ||= flow_order.selections
184
+ end
185
+
186
+ # @return ::Io::Flow::V0::Models::DeliveryOption
187
+ def flow_shipping_method
188
+ method_id = flow_shipping_method_ids.first
189
+
190
+ delivery = flow_order.deliveries.detect do |d|
191
+ d.options.detect do |o|
192
+ o.id == method_id
193
+ end
194
+ end
195
+
196
+ delivery.options.detect { |o| o.id == method_id }
197
+ end
198
+
199
+ def payment
200
+ @payment ||= Payment.find_or_create_by(id: order.id)
201
+ end
202
+
203
+ def shipping
204
+ @shippipng ||=
205
+ begin
206
+ # get rid of anything that could be a holdover from the
207
+ # workarea checkout
208
+ Workarea::Shipping.where(order_id: order.id).destroy_all
209
+ Shipping.create(order_id: order.id)
210
+ end
211
+ end
212
+
213
+ # @return [::Io::Flow::V0::Models::OrderPriceDetail]
214
+ def flow_shipping_prices
215
+ flow_order.prices.reject { |p| p.name == 'Item subtotal' }
216
+ end
217
+
218
+ def total_order
219
+ Pricing::ShippingTotals.new(shipping).total
220
+ Pricing::OrderTotals.new(pricing_order, [shipping]).total
221
+
222
+ order.save!
223
+ shipping.save!
224
+ end
225
+
226
+ def inventory
227
+ @inventory ||= Inventory::Transaction.from_order(
228
+ order.id,
229
+ order.items.inject({}) do |memo, item|
230
+ memo[item.sku] ||= 0
231
+ memo[item.sku] += item.quantity
232
+ memo
233
+ end
234
+ )
235
+ end
236
+
237
+ def flow_billing_address
238
+ flow_payments.first.address || flow_order.destination
239
+ end
240
+ end
241
+ end
242
+ end