workarea-core 3.4.44 → 3.5.0.beta.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 (427) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +52 -0
  3. data/app/assets/javascripts/workarea/core/modules/duplicate_id.js +1 -5
  4. data/app/assets/javascripts/workarea/core/modules/style_guide_autocomplete_fields.js +9 -42
  5. data/app/assets/javascripts/workarea/core/modules/url.js +14 -0
  6. data/app/controllers/workarea/application_controller.rb +5 -1
  7. data/app/controllers/workarea/authentication.rb +15 -26
  8. data/app/controllers/workarea/authorization.rb +3 -3
  9. data/app/controllers/workarea/current_referrer.rb +1 -2
  10. data/app/controllers/workarea/current_release.rb +1 -1
  11. data/app/controllers/workarea/current_segments.rb +52 -0
  12. data/app/controllers/workarea/current_tracking.rb +45 -0
  13. data/app/controllers/workarea/http_caching.rb +30 -0
  14. data/app/controllers/workarea/impersonation.rb +18 -44
  15. data/app/helpers/workarea/schema_org_helper.rb +21 -0
  16. data/app/mailers/workarea/application_mailer.rb +2 -4
  17. data/app/middleware/workarea/application_middleware.rb +44 -0
  18. data/app/middleware/workarea/query_cache_middleware.rb +55 -0
  19. data/app/middleware/workarea/release_server_middleware.rb +1 -1
  20. data/app/models/workarea/application_document.rb +1 -1
  21. data/app/models/workarea/bulk_action/product_edit.rb +6 -6
  22. data/app/models/workarea/calculate_percent_change.rb +1 -1
  23. data/app/models/workarea/catalog/category.rb +0 -2
  24. data/app/models/workarea/catalog/product.rb +19 -2
  25. data/app/models/workarea/checkout.rb +18 -6
  26. data/app/models/workarea/checkout/collect_payment.rb +10 -1
  27. data/app/models/workarea/checkout/fraud/analyzer.rb +44 -0
  28. data/app/models/workarea/checkout/fraud/no_decision_analyzer.rb +14 -0
  29. data/app/models/workarea/checkout/fraud/test_analyzer.rb +26 -0
  30. data/app/models/workarea/configuration/admin.rb +25 -0
  31. data/app/models/workarea/configuration/params.rb +45 -0
  32. data/app/models/workarea/content.rb +12 -82
  33. data/app/models/workarea/content/asset.rb +5 -18
  34. data/app/models/workarea/content/block.rb +8 -2
  35. data/app/models/workarea/content/block_draft.rb +7 -2
  36. data/app/models/workarea/content/block_type.rb +2 -2
  37. data/app/models/workarea/content/block_type_definition.rb +4 -0
  38. data/app/models/workarea/content/preset.rb +1 -1
  39. data/app/models/workarea/data_file/csv.rb +6 -8
  40. data/app/models/workarea/data_file/import.rb +9 -1
  41. data/app/models/workarea/data_file/json.rb +1 -20
  42. data/app/models/workarea/data_file/operation.rb +0 -4
  43. data/app/models/workarea/data_file/tax_rates.rb +3 -0
  44. data/app/models/workarea/featured_products.rb +8 -0
  45. data/app/models/workarea/fulfillment/policies/base.rb +21 -0
  46. data/app/models/workarea/fulfillment/policies/download.rb +21 -0
  47. data/app/models/workarea/fulfillment/policies/ignore.rb +11 -0
  48. data/app/models/workarea/fulfillment/policies/ship.rb +15 -0
  49. data/app/models/workarea/fulfillment/sku.rb +72 -0
  50. data/app/models/workarea/fulfillment/token.rb +36 -0
  51. data/app/models/workarea/inquiry.rb +1 -2
  52. data/app/models/workarea/insights/customer_acquisition.rb +5 -9
  53. data/app/models/workarea/insights/trending_products.rb +2 -2
  54. data/app/models/workarea/insights/trending_searches.rb +2 -2
  55. data/app/models/workarea/inventory/collection.rb +30 -0
  56. data/app/models/workarea/inventory/collection_status.rb +40 -0
  57. data/app/models/workarea/metrics/affinity.rb +33 -0
  58. data/app/models/workarea/metrics/country_by_day.rb +4 -0
  59. data/app/models/workarea/metrics/product_by_day.rb +3 -0
  60. data/app/models/workarea/metrics/product_by_week.rb +2 -0
  61. data/app/models/workarea/metrics/product_for_last_week.rb +8 -12
  62. data/app/models/workarea/metrics/sales_by_day.rb +5 -0
  63. data/app/models/workarea/metrics/search_by_day.rb +1 -3
  64. data/app/models/workarea/metrics/search_for_last_week.rb +5 -11
  65. data/app/models/workarea/metrics/segment_by_day.rb +31 -0
  66. data/app/models/workarea/metrics/sku_by_day.rb +3 -0
  67. data/app/models/workarea/metrics/tender_by_day.rb +11 -0
  68. data/app/models/workarea/metrics/update_user_aggregations.rb +77 -0
  69. data/app/models/workarea/metrics/user.rb +73 -87
  70. data/app/models/workarea/navigation/breadcrumbs.rb +10 -1
  71. data/app/models/workarea/order.rb +47 -4
  72. data/app/models/workarea/order/fraud_decision.rb +18 -0
  73. data/app/models/workarea/order/item.rb +5 -0
  74. data/app/models/workarea/order/queries.rb +1 -0
  75. data/app/models/workarea/order/status.rb +10 -1
  76. data/app/models/workarea/payment.rb +7 -2
  77. data/app/models/workarea/payment/credit_card.rb +12 -0
  78. data/app/models/workarea/pricing/cache_key.rb +9 -3
  79. data/app/models/workarea/pricing/calculator.rb +5 -1
  80. data/app/models/workarea/pricing/calculators/tax_calculator.rb +32 -5
  81. data/app/models/workarea/pricing/discount.rb +2 -3
  82. data/app/models/workarea/pricing/discount/application_group.rb +8 -3
  83. data/app/models/workarea/pricing/discount/free_gift.rb +2 -1
  84. data/app/models/workarea/pricing/discount/redemption.rb +1 -1
  85. data/app/models/workarea/pricing/item_tax_applier.rb +41 -0
  86. data/app/models/workarea/pricing/price.rb +1 -0
  87. data/app/models/workarea/pricing/request.rb +11 -0
  88. data/app/models/workarea/pricing/sku.rb +1 -0
  89. data/app/models/workarea/pricing/tax_application.rb +21 -0
  90. data/app/models/workarea/pricing/tax_applier.rb +12 -15
  91. data/app/models/workarea/pricing/unsupported_segmentation.rb +22 -0
  92. data/app/models/workarea/product_rule.rb +5 -0
  93. data/app/models/workarea/releasable.rb +83 -89
  94. data/app/models/workarea/release.rb +72 -99
  95. data/app/models/workarea/release/activation.rb +45 -0
  96. data/app/models/workarea/release/changes.rb +45 -0
  97. data/app/models/workarea/release/changeset.rb +42 -52
  98. data/app/models/workarea/release/preview.rb +28 -0
  99. data/app/models/workarea/release/status.rb +2 -24
  100. data/app/models/workarea/release_session.rb +11 -11
  101. data/app/models/workarea/search/admin.rb +17 -39
  102. data/app/models/workarea/search/admin/catalog_product.rb +1 -2
  103. data/app/models/workarea/search/admin/fulfillment_sku.rb +27 -0
  104. data/app/models/workarea/search/admin/order.rb +1 -1
  105. data/app/models/workarea/search/admin/pricing_discount.rb +1 -1
  106. data/app/models/workarea/search/admin/release.rb +1 -4
  107. data/app/models/workarea/search/admin/segment.rb +19 -0
  108. data/app/models/workarea/search/order_text.rb +23 -6
  109. data/app/models/workarea/search/storefront.rb +33 -29
  110. data/app/models/workarea/search/storefront/category_query.rb +152 -0
  111. data/app/models/workarea/search/storefront/product/categories.rb +11 -45
  112. data/app/models/workarea/segment.rb +54 -0
  113. data/app/models/workarea/segment/first_time_customer.rb +8 -0
  114. data/app/models/workarea/segment/first_time_visitor.rb +12 -0
  115. data/app/models/workarea/segment/life_cycle.rb +44 -0
  116. data/app/models/workarea/segment/loyal_customer.rb +12 -0
  117. data/app/models/workarea/segment/returning_customer.rb +14 -0
  118. data/app/models/workarea/segment/returning_visitor.rb +12 -0
  119. data/app/models/workarea/segment/rules/base.rb +16 -0
  120. data/app/models/workarea/segment/rules/browser_info.rb +29 -0
  121. data/app/models/workarea/segment/rules/geolocation.rb +29 -0
  122. data/app/models/workarea/segment/rules/geolocation_option.rb +53 -0
  123. data/app/models/workarea/segment/rules/last_order.rb +14 -0
  124. data/app/models/workarea/segment/rules/logged_in.rb +13 -0
  125. data/app/models/workarea/segment/rules/orders.rb +17 -0
  126. data/app/models/workarea/segment/rules/revenue.rb +17 -0
  127. data/app/models/workarea/segment/rules/sessions.rb +17 -0
  128. data/app/models/workarea/segment/rules/tags.rb +14 -0
  129. data/app/models/workarea/segment/rules/traffic_referrer.rb +18 -0
  130. data/app/models/workarea/segmentable.rb +66 -0
  131. data/app/models/workarea/sort.rb +14 -2
  132. data/app/models/workarea/tax/rate.rb +35 -1
  133. data/app/models/workarea/user/authorization.rb +19 -13
  134. data/app/models/workarea/user/login.rb +4 -0
  135. data/app/models/workarea/user/password_reset.rb +1 -3
  136. data/app/queries/workarea/categorization.rb +3 -3
  137. data/app/queries/workarea/featured_categorization.rb +53 -0
  138. data/app/queries/workarea/order_cancellation_metrics.rb +155 -0
  139. data/app/queries/workarea/order_item_details.rb +16 -3
  140. data/app/queries/workarea/order_metrics.rb +32 -3
  141. data/app/queries/workarea/product_primary_navigation.rb +13 -2
  142. data/app/queries/workarea/product_releases.rb +38 -0
  143. data/app/queries/workarea/recommendation/user_activity_based.rb +14 -6
  144. data/app/queries/workarea/reports/average_order_value.rb +1 -1
  145. data/app/queries/workarea/reports/customers.rb +14 -11
  146. data/app/queries/workarea/reports/first_time_vs_returning_sales.rb +1 -1
  147. data/app/queries/workarea/reports/group_by_time.rb +13 -17
  148. data/app/queries/workarea/reports/sales_by_category.rb +1 -1
  149. data/app/queries/workarea/reports/sales_by_country.rb +10 -3
  150. data/app/queries/workarea/reports/sales_by_discount.rb +1 -1
  151. data/app/queries/workarea/reports/sales_by_menu.rb +1 -1
  152. data/app/queries/workarea/reports/sales_by_product.rb +39 -4
  153. data/app/queries/workarea/reports/sales_by_sku.rb +39 -4
  154. data/app/queries/workarea/reports/sales_by_tender.rb +42 -0
  155. data/app/queries/workarea/reports/sales_by_traffic_referrer.rb +1 -1
  156. data/app/queries/workarea/reports/sales_over_time.rb +10 -3
  157. data/app/queries/workarea/reports/searches.rb +1 -1
  158. data/app/queries/workarea/reports/searches_over_time.rb +1 -1
  159. data/app/queries/workarea/reports/searches_without_results_over_time.rb +1 -1
  160. data/app/queries/workarea/search/admin_fulfillment_skus.rb +20 -0
  161. data/app/queries/workarea/search/admin_releases.rb +1 -4
  162. data/app/queries/workarea/search/admin_search.rb +0 -4
  163. data/app/queries/workarea/search/admin_segments.rb +16 -0
  164. data/app/queries/workarea/search/admin_sorting.rb +1 -1
  165. data/app/queries/workarea/search/pagination.rb +1 -4
  166. data/app/queries/workarea/search/product_display_rules.rb +40 -8
  167. data/app/queries/workarea/search/product_entries.rb +15 -1
  168. data/app/queries/workarea/search/product_search.rb +4 -1
  169. data/app/queries/workarea/search/storefront_search.rb +5 -4
  170. data/app/queries/workarea/search/storefront_search/exact_matches.rb +1 -1
  171. data/app/queries/workarea/search/storefront_search/response.rb +6 -4
  172. data/app/seeds/workarea/assets_seeds.rb +2 -1
  173. data/app/seeds/workarea/insights_seeds.rb +0 -23
  174. data/app/seeds/workarea/orders_seeds.rb +7 -6
  175. data/app/seeds/workarea/products_seeds.rb +2 -0
  176. data/app/seeds/workarea/segments_seeds.rb +8 -0
  177. data/app/seeds/workarea/tax_seeds.rb +3 -3
  178. data/app/services/workarea/cancel_order.rb +8 -3
  179. data/app/services/workarea/copy_order.rb +6 -0
  180. data/app/services/workarea/create_fulfillment.rb +5 -3
  181. data/app/services/workarea/direct_upload.rb +11 -19
  182. data/app/services/workarea/hash_update.rb +1 -18
  183. data/app/services/workarea/packaging.rb +1 -1
  184. data/app/services/workarea/save_publishing.rb +5 -1
  185. data/app/workers/sidekiq/callbacks.rb +4 -52
  186. data/app/workers/sidekiq/callbacks_worker.rb +4 -6
  187. data/app/workers/workarea/bulk_index_admin.rb +2 -2
  188. data/app/workers/workarea/bulk_index_products.rb +6 -5
  189. data/app/workers/workarea/bulk_index_searches.rb +5 -5
  190. data/app/workers/workarea/deactivate_stale_discounts.rb +3 -3
  191. data/app/workers/workarea/generate_insights.rb +1 -1
  192. data/app/workers/workarea/index_admin_search.rb +1 -0
  193. data/app/workers/workarea/index_categorization.rb +4 -7
  194. data/app/workers/workarea/index_category.rb +2 -1
  195. data/app/workers/workarea/index_category_changes.rb +11 -6
  196. data/app/workers/workarea/index_fulfillment_changes.rb +2 -1
  197. data/app/workers/workarea/index_help.rb +2 -1
  198. data/app/workers/workarea/index_page.rb +2 -1
  199. data/app/workers/workarea/index_payment_transactions.rb +2 -1
  200. data/app/workers/workarea/index_product.rb +4 -4
  201. data/app/workers/workarea/index_product_children.rb +4 -3
  202. data/app/workers/workarea/index_product_rule.rb +3 -2
  203. data/app/workers/workarea/index_search_customizations.rb +3 -2
  204. data/app/workers/workarea/index_skus.rb +5 -6
  205. data/app/workers/workarea/keep_product_index_fresh.rb +3 -5
  206. data/app/workers/workarea/process_import.rb +3 -3
  207. data/app/workers/workarea/process_search_recommendations.rb +5 -9
  208. data/app/workers/workarea/publish_release.rb +1 -0
  209. data/app/workers/workarea/save_metrics.rb +116 -0
  210. data/app/workers/workarea/save_order_cancellation_metrics.rb +35 -0
  211. data/app/workers/workarea/save_order_metrics.rb +10 -74
  212. data/app/workers/workarea/status_reporter.rb +2 -4
  213. data/app/workers/workarea/synchronize_user_metrics.rb +17 -0
  214. data/app/workers/workarea/update_payment_profile_email.rb +22 -0
  215. data/app/workers/workarea/verify_scheduled_releases.rb +4 -11
  216. data/config/initializers/00_configuration.rb +185 -0
  217. data/config/initializers/02_assets.rb +1 -0
  218. data/config/initializers/05_scheduled_jobs.rb +0 -7
  219. data/config/initializers/10_rack_middleware.rb +2 -5
  220. data/config/initializers/11_payment.rb +4 -0
  221. data/config/initializers/13_rack_attack.rb +2 -4
  222. data/config/initializers/14_content_block_types.rb +16 -16
  223. data/config/initializers/15_endpoint_monitoring.rb +3 -6
  224. data/config/initializers/{21_premailer.rb → 24_premailer.rb} +1 -0
  225. data/config/initializers/{20_i18n_js.rb → 25_i18n_js.rb} +0 -0
  226. data/config/locales/en.yml +13 -24
  227. data/lib/generators/workarea/content_block_type/templates/initializer.rb +1 -1
  228. data/lib/generators/workarea/install/USAGE +0 -1
  229. data/lib/generators/workarea/install/install_generator.rb +0 -21
  230. data/lib/generators/workarea/install/templates/initializer.rb.erb +1 -1
  231. data/lib/tasks/insights.rake +1 -0
  232. data/lib/tasks/migrate.rake +106 -0
  233. data/lib/tasks/search.rake +17 -19
  234. data/lib/tasks/tests.rake +1 -1
  235. data/lib/workarea.rb +102 -3
  236. data/lib/workarea/cache.rb +6 -35
  237. data/lib/workarea/changelog.rake +2 -2
  238. data/lib/workarea/configuration.rb +121 -148
  239. data/lib/workarea/configuration/administrable/definition.rb +42 -0
  240. data/lib/workarea/configuration/administrable/field.rb +79 -0
  241. data/lib/workarea/configuration/administrable/fieldset.rb +44 -0
  242. data/lib/workarea/configuration/administrable_options.rb +24 -0
  243. data/lib/workarea/configuration/cache_store.rb +3 -1
  244. data/lib/workarea/configuration/content_blocks.rb +17 -0
  245. data/lib/workarea/configuration/mongoid.rb +1 -4
  246. data/lib/workarea/configuration/session.rb +36 -0
  247. data/lib/workarea/configuration/sidekiq.rb +3 -1
  248. data/lib/workarea/core.rb +15 -11
  249. data/lib/workarea/core/engine.rb +3 -58
  250. data/lib/workarea/elasticsearch/document.rb +8 -15
  251. data/lib/workarea/ext/freedom_patches/action_view_cache_helper.rb +4 -6
  252. data/lib/workarea/ext/freedom_patches/active_support_duration.rb +14 -0
  253. data/lib/workarea/ext/freedom_patches/money.rb +11 -0
  254. data/lib/workarea/ext/freedom_patches/premailer.rb +6 -0
  255. data/lib/workarea/ext/freedom_patches/string.rb +19 -4
  256. data/lib/workarea/ext/mongoid/find_ordered.rb +2 -2
  257. data/lib/workarea/ext/mongoid/lookup_hash.rb +30 -0
  258. data/lib/workarea/geolocation.rb +24 -6
  259. data/lib/workarea/routes_constraints/super_admin.rb +1 -1
  260. data/lib/workarea/version.rb +3 -4
  261. data/lib/workarea/visit.rb +92 -0
  262. data/lib/workarea/warnings.rb +95 -0
  263. data/test/dummy/config/initializers/session_store.rb +1 -1
  264. data/test/fixtures/tax_rates.csv +3 -3
  265. data/test/generators/workarea/content_block_type_generator_test.rb +1 -1
  266. data/test/generators/workarea/install_generator_test.rb +0 -13
  267. data/test/integration/workarea/authentication_test.rb +27 -4
  268. data/test/integration/workarea/authorization_test.rb +5 -0
  269. data/test/integration/workarea/cache_varies_integration_test.rb +21 -23
  270. data/test/integration/workarea/monitoring_integration_test.rb +5 -10
  271. data/test/javascripts/duplicate_id_spec.js +1 -7
  272. data/test/javascripts/fixtures/{duplicate_id_fail.html.haml → duplicate_id.html.haml} +0 -1
  273. data/test/javascripts/form_submitting_controls_spec.js +0 -1
  274. data/test/lib/workarea/asset_endpoints/favicons_test.rb +11 -13
  275. data/test/lib/workarea/configuration/administrable/definition_test.rb +71 -0
  276. data/test/lib/workarea/configuration/administrable/field_test.rb +128 -0
  277. data/test/lib/workarea/configuration/administrable/fieldset_test.rb +78 -0
  278. data/test/lib/workarea/configuration/configuration_test.rb +20 -0
  279. data/test/lib/workarea/elasticsearch/document_test.rb +0 -20
  280. data/test/lib/workarea/elasticsearch/query_cache_test.rb +7 -7
  281. data/test/lib/workarea/ext/freedom_patches/money_test.rb +11 -0
  282. data/test/lib/workarea/ext/mongoid/lookup_hash_test.rb +86 -0
  283. data/test/lib/workarea/geolocation_test.rb +20 -0
  284. data/test/mailers/workarea/application_mailer_test.rb +1 -11
  285. data/test/middleware/workarea/query_cache_middleware_test.rb +55 -0
  286. data/test/models/workarea/checkout/collect_payment_test.rb +14 -6
  287. data/test/models/workarea/checkout_test.rb +31 -57
  288. data/test/models/workarea/configuration/params_test.rb +37 -0
  289. data/test/models/workarea/data_file/csv_test.rb +8 -73
  290. data/test/models/workarea/data_file/import_test.rb +31 -0
  291. data/test/models/workarea/data_file/json_test.rb +6 -48
  292. data/test/models/workarea/data_file/tax_test.rb +3 -0
  293. data/test/models/workarea/fulfillment/policies/download_test.rb +39 -0
  294. data/test/models/workarea/fulfillment/sku_test.rb +54 -0
  295. data/test/models/workarea/insights/best_customers_test.rb +5 -2
  296. data/test/models/workarea/insights/best_full_price_customers_test.rb +5 -2
  297. data/test/models/workarea/insights/customer_acquisition_test.rb +1 -1
  298. data/test/models/workarea/insights/customers_at_risk_test.rb +1 -1
  299. data/test/models/workarea/insights/low_aov_customers_test.rb +1 -1
  300. data/test/models/workarea/inventory/collection_test.rb +75 -0
  301. data/test/models/workarea/metrics/affinity_test.rb +85 -0
  302. data/test/models/workarea/metrics/product_by_week_test.rb +27 -31
  303. data/test/models/workarea/metrics/search_by_day_test.rb +3 -0
  304. data/test/models/workarea/metrics/search_by_week_test.rb +27 -31
  305. data/test/models/workarea/metrics/update_user_aggregations_test.rb +62 -0
  306. data/test/models/workarea/metrics/user_test.rb +146 -63
  307. data/test/models/workarea/navigation/breadcrumbs_test.rb +12 -2
  308. data/test/models/workarea/order/queries_test.rb +2 -0
  309. data/test/models/workarea/order_test.rb +44 -0
  310. data/test/models/workarea/payment/address_test.rb +109 -111
  311. data/test/models/workarea/payment/credit_card_integration_test.rb +0 -52
  312. data/test/models/workarea/payment/credit_card_test.rb +5 -0
  313. data/test/models/workarea/pricing/cache_key_test.rb +7 -1
  314. data/test/models/workarea/pricing/calculators/tax_calculator_test.rb +41 -1
  315. data/test/models/workarea/pricing/discount/collection_test.rb +27 -29
  316. data/test/models/workarea/pricing/discount_test.rb +22 -24
  317. data/test/models/workarea/pricing/item_tax_applier_test.rb +83 -0
  318. data/test/models/workarea/pricing/price_test.rb +9 -0
  319. data/test/models/workarea/pricing/request_test.rb +13 -0
  320. data/test/models/workarea/pricing/sku_test.rb +9 -0
  321. data/test/models/workarea/releasable_active_test.rb +113 -0
  322. data/test/models/workarea/releasable_test.rb +69 -120
  323. data/test/models/workarea/release/changeset_test.rb +41 -0
  324. data/test/models/workarea/release_jobs_test.rb +52 -0
  325. data/test/models/workarea/release_previewing_test.rb +43 -0
  326. data/test/models/workarea/release_test.rb +59 -153
  327. data/test/models/workarea/search/admin/content_asset_test.rb +26 -28
  328. data/test/models/workarea/search/order_text_test.rb +35 -0
  329. data/test/models/workarea/search/storefront/category_query_test.rb +81 -0
  330. data/test/models/workarea/search/storefront/product/categories_test.rb +10 -70
  331. data/test/models/workarea/search/storefront/product_test.rb +10 -11
  332. data/test/models/workarea/search/storefront_test.rb +1 -13
  333. data/test/models/workarea/segment/life_cycle_test.rb +24 -0
  334. data/test/models/workarea/segment/rules/browser_info_test.rb +33 -0
  335. data/test/models/workarea/segment/rules/geolocation_option_test.rb +16 -0
  336. data/test/models/workarea/segment/rules/geolocation_test.rb +49 -0
  337. data/test/models/workarea/segment/rules/last_order_test.rb +32 -0
  338. data/test/models/workarea/segment/rules/logged_in_test.rb +25 -0
  339. data/test/models/workarea/segment/rules/orders_test.rb +59 -0
  340. data/test/models/workarea/segment/rules/revenue_test.rb +59 -0
  341. data/test/models/workarea/segment/rules/sessions_test.rb +26 -0
  342. data/test/models/workarea/segment/rules/tags_test.rb +27 -0
  343. data/test/models/workarea/segment/rules/traffic_referrer_test.rb +31 -0
  344. data/test/models/workarea/segment_test.rb +80 -0
  345. data/test/models/workarea/segmentable_test.rb +74 -0
  346. data/test/models/workarea/shipping/address_test.rb +109 -111
  347. data/test/models/workarea/shipping/sku_test.rb +8 -12
  348. data/test/models/workarea/user/password_reset_test.rb +4 -12
  349. data/test/models/workarea/user_test.rb +13 -10
  350. data/test/queries/workarea/admin_search_query_wrapper_test.rb +21 -25
  351. data/test/queries/workarea/categorization_test.rb +49 -0
  352. data/test/queries/workarea/featured_categorization_test.rb +66 -0
  353. data/test/queries/workarea/order_cancellation_metrics_test.rb +203 -0
  354. data/test/queries/workarea/order_item_details_test.rb +17 -0
  355. data/test/queries/workarea/order_metrics_test.rb +12 -0
  356. data/test/queries/workarea/product_releases_test.rb +56 -0
  357. data/test/queries/workarea/recommendation/searches_test.rb +3 -3
  358. data/test/queries/workarea/recommendation/user_activity_based_test.rb +4 -4
  359. data/test/queries/workarea/reports/customers_test.rb +12 -8
  360. data/test/queries/workarea/reports/report_test.rb +4 -6
  361. data/test/queries/workarea/reports/sales_by_country_test.rb +18 -3
  362. data/test/queries/workarea/reports/sales_by_product_test.rb +28 -8
  363. data/test/queries/workarea/reports/sales_by_sku_test.rb +28 -8
  364. data/test/queries/workarea/reports/sales_by_tender_test.rb +100 -0
  365. data/test/queries/workarea/reports/sales_by_traffic_referrer_test.rb +6 -6
  366. data/test/queries/workarea/search/admin_releases_test.rb +1 -26
  367. data/test/queries/workarea/search/admin_search_test.rb +0 -10
  368. data/test/queries/workarea/search/admin_users_test.rb +2 -2
  369. data/test/queries/workarea/search/category_browse_test.rb +53 -0
  370. data/test/queries/workarea/search/facet_sorting/size_test.rb +11 -13
  371. data/test/queries/workarea/search/pagination_test.rb +9 -26
  372. data/test/queries/workarea/search/product_entries_test.rb +27 -0
  373. data/test/queries/workarea/search/product_search_test.rb +0 -16
  374. data/test/queries/workarea/search/storefront_search/response_test.rb +26 -0
  375. data/test/queries/workarea/search/storefront_search_test.rb +34 -36
  376. data/test/services/workarea/cancel_order_test.rb +27 -13
  377. data/test/services/workarea/copy_order_test.rb +17 -0
  378. data/test/services/workarea/direct_upload_test.rb +1 -46
  379. data/test/services/workarea/export_report_test.rb +41 -45
  380. data/test/services/workarea/hash_update_test.rb +12 -12
  381. data/test/services/workarea/packaging_test.rb +9 -11
  382. data/test/services/workarea/save_publishing_test.rb +23 -0
  383. data/test/workers/sidekiq/callbacks_test.rb +0 -22
  384. data/test/workers/workarea/deactivate_stale_discounts_test.rb +2 -2
  385. data/test/workers/workarea/index_category_changes_test.rb +5 -7
  386. data/test/workers/workarea/keep_product_index_fresh_test.rb +1 -1
  387. data/test/workers/workarea/process_import_test.rb +0 -6
  388. data/test/workers/workarea/process_search_recommendations_test.rb +4 -5
  389. data/test/workers/workarea/status_reporter_test.rb +2 -1
  390. data/test/workers/workarea/synchronize_user_metrics_test.rb +57 -0
  391. data/test/workers/workarea/update_payment_profile_email_test.rb +27 -0
  392. data/test/workers/workarea/verify_scheduled_releases_test.rb +0 -26
  393. data/workarea-core.gemspec +12 -10
  394. metadata +188 -78
  395. data/app/assets/javascripts/workarea/core/templates/ui_menu_item.jst.ejs +0 -10
  396. data/app/controllers/workarea/admin_guest_browsing.rb +0 -54
  397. data/app/middleware/workarea/rack_cache_config_middleware.rb +0 -19
  398. data/app/queries/workarea/search/search_suggestions.rb +0 -43
  399. data/app/workers/workarea/bust_discount_cache.rb +0 -16
  400. data/app/workers/workarea/clean_user_activity.rb +0 -11
  401. data/app/workers/workarea/undo_release.rb +0 -15
  402. data/app/workers/workarea/update_email.rb +0 -33
  403. data/lib/generators/workarea/docker/USAGE +0 -16
  404. data/lib/generators/workarea/docker/docker_generator.rb +0 -61
  405. data/lib/generators/workarea/docker/templates/.env.erb +0 -6
  406. data/lib/generators/workarea/docker/templates/Dockerfile.erb +0 -48
  407. data/lib/generators/workarea/docker/templates/docker-compose.yml.erb +0 -72
  408. data/lib/generators/workarea/docker/templates/docker-entrypoint.sh.erb +0 -6
  409. data/lib/generators/workarea/docker/templates/docker-sync.yml.erb +0 -8
  410. data/lib/generators/workarea/docker/templates/docker-wait.sh +0 -11
  411. data/lib/generators/workarea/docker/templates/docker.env +0 -16
  412. data/lib/generators/workarea/docker/templates/docker_init.rb.erb +0 -29
  413. data/lib/workarea/configuration/headless_chrome.rb +0 -42
  414. data/lib/workarea/configuration/puma.rb +0 -37
  415. data/lib/workarea/ext/freedom_patches/i18n_js.rb +0 -27
  416. data/lib/workarea/ext/freedom_patches/mongoid_localized_defaults.rb +0 -25
  417. data/lib/workarea/ext/jbuilder/jbuilder_cache.rb +0 -29
  418. data/lib/workarea/ext/referer_parser/parser.decorator +0 -43
  419. data/lib/workarea/queues_pauser.rb +0 -26
  420. data/lib/workarea/robots.rb +0 -9
  421. data/test/generators/workarea/docker_generator_test.rb +0 -156
  422. data/test/javascripts/fixtures/duplicate_id_pass.html.haml +0 -2
  423. data/test/lib/workarea/ext/freedom_patches/mongoid_localized_defaults_test.rb +0 -25
  424. data/test/lib/workarea/ext/referer_parser/parser_test.rb +0 -20
  425. data/test/queries/workarea/search/search_suggestions_test.rb +0 -29
  426. data/test/workers/workarea/undo_release_test.rb +0 -23
  427. data/test/workers/workarea/update_email_test.rb +0 -39
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ module SchemaOrgHelper
3
+ def render_schema_org(schema)
4
+ tag.script(schema.to_json.html_safe, type: 'application/ld+json')
5
+ end
6
+
7
+ def email_action_schema(target, name, description = nil)
8
+ {
9
+ '@context': 'http://schema.org',
10
+ '@type': 'EmailMessage',
11
+ 'potentialAction': {
12
+ '@type': 'ViewAction',
13
+ 'target': target,
14
+ 'url': target,
15
+ 'name': name
16
+ },
17
+ 'description': description || name
18
+ }
19
+ end
20
+ end
21
+ end
@@ -4,13 +4,11 @@ module Workarea
4
4
 
5
5
  add_template_helper Workarea::PluginsHelper
6
6
  add_template_helper Workarea::ApplicationHelper
7
+ add_template_helper Workarea::SchemaOrgHelper
7
8
  default from: -> (*) { Workarea.config.email_from }
8
9
 
9
10
  def default_url_options(options = {})
10
- # super isn't returning the configured options, so manually merge them in
11
- super
12
- .merge(Rails.application.config.action_mailer.default_url_options.to_h)
13
- .merge(host: Workarea.config.host)
11
+ super.merge(host: Workarea.config.host)
14
12
  end
15
13
  end
16
14
  end
@@ -0,0 +1,44 @@
1
+ module Workarea
2
+ class ApplicationMiddleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ request = Rack::Request.new(env)
9
+ return @app.call(env) if request.path =~ /(jpe?g|png|ico|gif|css|js)$/
10
+
11
+ setup_environment(env, request)
12
+ set_segment_request_headers(env)
13
+ status, headers, body = @app.call(env)
14
+ set_segment_response_headers(env, headers)
15
+
16
+ [status, headers, body]
17
+ end
18
+
19
+ def setup_environment(env, request)
20
+ env['workarea.visit'] = Visit.new(env)
21
+ env['workarea.cache_varies'] = Cache::Varies.new(env['workarea.visit']).to_s
22
+ env['rack-cache.cache_key'] = Cache::RackCacheKey
23
+ env['rack-cache.force-pass'] = env['workarea.visit'].admin?
24
+ end
25
+
26
+ def set_segment_request_headers(env)
27
+ env['HTTP_X_WORKAREA_SEGMENTS'] = normalize_segment_ids(env['workarea.visit'])
28
+ end
29
+
30
+ def set_segment_response_headers(env, headers)
31
+ headers['X-Workarea-Segments'] = normalize_segment_ids(env['workarea.visit'])
32
+
33
+ if headers['X-Workarea-Segmented-Content'] == 'true'
34
+ headers['Cache-Control'] = 'private, no-cache, max-age=0'
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def normalize_segment_ids(visit)
41
+ visit.applied_segments.map(&:id).sort.join(',')
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ module Workarea
2
+ # Execute sidekiq jobs with query caches enabled. Each job can specify one or
3
+ # both query_caches to use via `query_cache`, `mongoid_query_cache`, or
4
+ # `elasticsearch_query_cache` options.
5
+ #
6
+ # @return [ Object ] The result of the call.
7
+ #
8
+ class QueryCacheMiddleware
9
+ def initialize(options = {})
10
+ @options = options
11
+ end
12
+
13
+ def call(worker, msg, queue)
14
+ cache_options = CacheOptions.new(worker.class.sidekiq_options)
15
+ return yield if cache_options.none?
16
+
17
+ if cache_options.all?
18
+ Mongoid::QueryCache.cache do
19
+ Elasticsearch::QueryCache.cache do
20
+ yield
21
+ end
22
+ end
23
+ elsif cache_options.mongoid?
24
+ Mongoid::QueryCache.cache { yield }
25
+ elsif cache_options.elasticsearch?
26
+ Elasticsearch::QueryCache.cache { yield }
27
+ end
28
+ ensure
29
+ Mongoid::QueryCache.clear_cache
30
+ Elasticsearch::QueryCache.clear_cache
31
+ end
32
+
33
+ class CacheOptions
34
+ def initialize(options)
35
+ @options = options
36
+ end
37
+
38
+ def none?
39
+ !mongoid? && !elasticsearch?
40
+ end
41
+
42
+ def all?
43
+ mongoid? && elasticsearch?
44
+ end
45
+
46
+ def mongoid?
47
+ !!(@options['mongoid_query_cache'] || @options['query_cache'])
48
+ end
49
+
50
+ def elasticsearch?
51
+ !!(@options['elasticsearch_query_cache'] || @options['query_cache'])
52
+ end
53
+ end
54
+ end
55
+ end
@@ -5,7 +5,7 @@ module Workarea
5
5
  end
6
6
 
7
7
  def call(worker, msg, queue)
8
- Release.with_current(nil) { yield }
8
+ Release.without_current { yield }
9
9
  end
10
10
  end
11
11
  end
@@ -14,7 +14,7 @@ module Workarea
14
14
  end
15
15
 
16
16
  def releasable?
17
- false
17
+ is_a?(Releasable)
18
18
  end
19
19
 
20
20
  private
@@ -36,15 +36,15 @@ module Workarea
36
36
  end
37
37
 
38
38
  def apply_details!(product)
39
- product.details = HashUpdate
40
- .new(original: product.details, adds: add_details, removes: remove_details)
41
- .result
39
+ HashUpdate
40
+ .new(adds: add_details, removes: remove_details)
41
+ .apply(product.details)
42
42
  end
43
43
 
44
44
  def apply_filters!(product)
45
- product.filters = HashUpdate
46
- .new(original: product.filters, adds: add_filters, removes: remove_filters)
47
- .result
45
+ HashUpdate
46
+ .new(adds: add_filters, removes: remove_filters)
47
+ .apply(product.filters)
48
48
  end
49
49
 
50
50
  def apply_pricing!(product)
@@ -1,7 +1,7 @@
1
1
  module Workarea
2
2
  module CalculatePercentChange
3
3
  def calculate_percent_change(first, second)
4
- return nil if first.zero?
4
+ return nil if first.blank? || first.zero?
5
5
  ((second.to_f - first) / first.to_f) * 100
6
6
  end
7
7
  end
@@ -23,8 +23,6 @@ module Workarea
23
23
  validates :client_id, uniqueness: true, allow_blank: true
24
24
 
25
25
  scope :recent, ->(l = 5) { order_by([:created_at, :desc]).limit(l) }
26
- scope :by_product, ->(id) { self.in(product_ids: id) }
27
-
28
26
  index({ client_id: 1 })
29
27
  end
30
28
  end
@@ -12,7 +12,6 @@ module Workarea
12
12
  field :name, type: String, localize: true
13
13
  field :filters, type: Hash, default: {}, localize: true
14
14
  field :template, type: String, default: 'generic'
15
- field :digital, type: Boolean, default: false
16
15
  field :customizations, type: String
17
16
  field :browser_title, type: String, localize: true
18
17
  field :meta_description, type: String, localize: true
@@ -21,6 +20,14 @@ module Workarea
21
20
  field :purchasable, type: Boolean, default: true
22
21
  field :default_category_id, type: String
23
22
 
23
+ # DEPRECATED. This field will be remove in v3.6 in favor of using
24
+ # Fulfillment::SKU to determine behavior in checkout for items not
25
+ # requiring phsyical fulfillment.
26
+ #
27
+ # TODO: remove in v3.6
28
+ #
29
+ field :digital, type: Boolean, default: false
30
+
24
31
  index({ 'variants.sku': 1 })
25
32
  index({ last_indexed_at: 1 })
26
33
  index({ 'images.option': 1 })
@@ -119,7 +126,17 @@ module Workarea
119
126
  end
120
127
 
121
128
  def active?
122
- super && variants.active.any?
129
+ super && active_by_relations?
130
+ end
131
+
132
+ # This hook allows plugins extending this model a place to hook into
133
+ # #active? without overriding all the logic in that method's `super`. For
134
+ # example, package products.
135
+ #
136
+ # @return [Boolean]
137
+ #
138
+ def active_by_relations?
139
+ variants.active.any?
123
140
  end
124
141
 
125
142
  # Whether to allow purchasing on this product. This is always false if
@@ -158,14 +158,10 @@ module Workarea
158
158
  # Used in auto completing an order for a logged in user.
159
159
  #
160
160
  # @param [Hash] parameters for updating
161
- # @return [Boolean] whether the update was successful.
161
+ # @return [self]
162
162
  #
163
163
  def update(params = {})
164
- return true if params.blank?
165
-
166
- steps.reduce(true) do |result, step|
167
- result &= step.new(self).update(params)
168
- end
164
+ steps.each { |s| s.new(self).update(params) }
169
165
  end
170
166
 
171
167
  # Whether this checkout needs any further information
@@ -191,6 +187,9 @@ module Workarea
191
187
  return false unless shippable?
192
188
  return false unless payable?
193
189
 
190
+ fraud_analyzer.decide!
191
+ return false if fraud_analyzer.fraud_suspected?
192
+
194
193
  inventory.purchase
195
194
  return false unless inventory.captured?
196
195
 
@@ -221,6 +220,15 @@ module Workarea
221
220
  payment.valid? && payment_collection.valid?
222
221
  end
223
222
 
223
+ # Recalculate the amounts on tenders if payment is persisted.
224
+ #
225
+ # @return [Boolean, nil]
226
+ #
227
+ def adjust_tender_amounts!
228
+ return unless payment.persisted?
229
+ payment.adjust_tender_amounts(order.total_price)
230
+ end
231
+
224
232
  private
225
233
 
226
234
  def auto_complete
@@ -234,5 +242,9 @@ module Workarea
234
242
  def place_order_side_effects
235
243
  CreateFulfillment.new(order).perform
236
244
  end
245
+
246
+ def fraud_analyzer
247
+ @fraud_analyzer ||= Workarea.config.fraud_analyzer.constantize.new(self)
248
+ end
237
249
  end
238
250
  end
@@ -33,7 +33,16 @@ module Workarea
33
33
  end
34
34
 
35
35
  def action
36
- Workarea.config.auto_capture ? 'purchase!' : 'authorize!'
36
+ # TODO deprecated, remove in v3.6
37
+ return 'purchase!' if Workarea.config.auto_capture
38
+
39
+ if @order.items.all?(&:requires_shipping?)
40
+ Workarea.config.checkout_payment_action[:shipped]
41
+ elsif @order.items.any?(&:requires_shipping?)
42
+ Workarea.config.checkout_payment_action[:mixed]
43
+ else
44
+ Workarea.config.checkout_payment_action[:not_shipped]
45
+ end
37
46
  end
38
47
  end
39
48
  end
@@ -0,0 +1,44 @@
1
+ module Workarea
2
+ class Checkout
3
+ module Fraud
4
+ class Analyzer
5
+ attr_reader :checkout
6
+
7
+ delegate :order, :user, :payment, :payment_profile, :shipping, :shippings,
8
+ to: :checkout, allow_nil: true
9
+ delegate :fraud_suspected?, to: :order
10
+
11
+ def initialize(checkout)
12
+ @checkout = checkout
13
+ end
14
+
15
+ def decide!
16
+ begin
17
+ decision = make_decision.tap { |r| r.analyzer = self.class.name }
18
+ rescue => e
19
+ decision = error_decision(e.message)
20
+ ensure
21
+ order.set_fraud_decision!(decision)
22
+ end
23
+ end
24
+
25
+ # Gets a decision about the fraudlence of a given checkout
26
+ #
27
+ # @param [Workarea::Checkout] checkout
28
+ #
29
+ # @return [Workarea::Order::FraudDecision]
30
+ #
31
+ def make_decision(checkout = nil)
32
+ raise(NotImplementedError, "#{self.class} must implement the #make_decision method")
33
+ end
34
+
35
+ def error_decision(message)
36
+ Workarea::Order::FraudDecision.new(
37
+ decision: :no_decision,
38
+ message: "An error occured during the fraud check: #{message}"
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ module Workarea
2
+ class Checkout
3
+ module Fraud
4
+ class NoDecisionAnalyzer < Analyzer
5
+ def make_decision
6
+ Workarea::Order::FraudDecision.new(
7
+ decision: :no_decision,
8
+ message: I18n.t('workarea.storefront.fraud.default_message')
9
+ )
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module Workarea
2
+ class Checkout
3
+ module Fraud
4
+ class TestAnalyzer < Analyzer
5
+ def make_decision
6
+ if order.email == "decline@workarea.com"
7
+ Workarea::Order::FraudDecision.new(
8
+ decision: :declined,
9
+ message: "Forced test fraud decline."
10
+ )
11
+ elsif order.email == "approved@workarea.com"
12
+ Workarea::Order::FraudDecision.new(
13
+ decision: :approved,
14
+ message: "Forced test fraud approval."
15
+ )
16
+ else
17
+ Workarea::Order::FraudDecision.new(
18
+ decision: :no_decision,
19
+ message: "Workarea default fraud check. Automatic no decision."
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Workarea
2
+ module Configuration
3
+ class Admin
4
+ include ApplicationDocument
5
+ include ::Mongoid::Encrypted
6
+
7
+ delegate :definition, to: :class
8
+
9
+ def self.instance
10
+ first || create
11
+ end
12
+
13
+ def self.definition
14
+ Workarea.config.admin_definition
15
+ end
16
+
17
+ definition.fields.each do |f|
18
+ field f.key,
19
+ type: f.type_class,
20
+ default: f.default,
21
+ encrypted: f.encrypted?
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ module Workarea
2
+ module Configuration
3
+ class Params
4
+ def initialize(params)
5
+ @params = params
6
+ end
7
+
8
+ def to_h
9
+ Admin.definition.fields.each_with_object({}) do |field, memo|
10
+ next unless @params.key?(field.key)
11
+ value = @params[field.key]
12
+
13
+ formatted_value =
14
+ if value.present? && respond_to?(field.type)
15
+ send(field.type, field, value)
16
+ else
17
+ value
18
+ end
19
+
20
+ memo[field.key] =
21
+ if formatted_value.blank? && !field.allow_blank?
22
+ field.default
23
+ else
24
+ formatted_value
25
+ end
26
+ end
27
+ end
28
+
29
+ def array(field, value)
30
+ Array.wrap(CSV.parse(value).first).map(&:strip)
31
+ end
32
+
33
+ def hash(field, value)
34
+ value.each_slice(2)
35
+ .to_h
36
+ .reject { |k, v| k.blank? || v.blank? }
37
+ .transform_values { |v| field.values_type_class.mongoize(v) }
38
+ end
39
+
40
+ def duration(field, value)
41
+ value.first.to_i.send(value.last.to_sym)
42
+ end
43
+ end
44
+ end
45
+ end