workarea-core 3.4.45 → 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/collect_payment.rb +10 -1
  26. data/app/models/workarea/checkout/fraud/analyzer.rb +44 -0
  27. data/app/models/workarea/checkout/fraud/no_decision_analyzer.rb +14 -0
  28. data/app/models/workarea/checkout/fraud/test_analyzer.rb +26 -0
  29. data/app/models/workarea/checkout.rb +18 -6
  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/asset.rb +5 -18
  33. data/app/models/workarea/content/block.rb +8 -2
  34. data/app/models/workarea/content/block_draft.rb +7 -2
  35. data/app/models/workarea/content/block_type.rb +2 -2
  36. data/app/models/workarea/content/block_type_definition.rb +4 -0
  37. data/app/models/workarea/content/preset.rb +1 -1
  38. data/app/models/workarea/content.rb +12 -82
  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/fraud_decision.rb +18 -0
  72. data/app/models/workarea/order/item.rb +5 -0
  73. data/app/models/workarea/order/queries.rb +1 -0
  74. data/app/models/workarea/order/status.rb +10 -1
  75. data/app/models/workarea/order.rb +47 -4
  76. data/app/models/workarea/payment/credit_card.rb +12 -0
  77. data/app/models/workarea/payment.rb +7 -2
  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/application_group.rb +8 -3
  82. data/app/models/workarea/pricing/discount/free_gift.rb +2 -1
  83. data/app/models/workarea/pricing/discount/redemption.rb +1 -1
  84. data/app/models/workarea/pricing/discount.rb +2 -3
  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/activation.rb +45 -0
  95. data/app/models/workarea/release/changes.rb +45 -0
  96. data/app/models/workarea/release/changeset.rb +42 -52
  97. data/app/models/workarea/release/preview.rb +28 -0
  98. data/app/models/workarea/release/status.rb +2 -24
  99. data/app/models/workarea/release.rb +72 -99
  100. data/app/models/workarea/release_session.rb +11 -11
  101. data/app/models/workarea/search/admin/catalog_product.rb +1 -2
  102. data/app/models/workarea/search/admin/fulfillment_sku.rb +27 -0
  103. data/app/models/workarea/search/admin/order.rb +1 -1
  104. data/app/models/workarea/search/admin/pricing_discount.rb +1 -1
  105. data/app/models/workarea/search/admin/release.rb +1 -4
  106. data/app/models/workarea/search/admin/segment.rb +19 -0
  107. data/app/models/workarea/search/admin.rb +17 -39
  108. data/app/models/workarea/search/order_text.rb +23 -6
  109. data/app/models/workarea/search/storefront/category_query.rb +152 -0
  110. data/app/models/workarea/search/storefront/product/categories.rb +11 -45
  111. data/app/models/workarea/search/storefront.rb +33 -29
  112. data/app/models/workarea/segment/first_time_customer.rb +8 -0
  113. data/app/models/workarea/segment/first_time_visitor.rb +12 -0
  114. data/app/models/workarea/segment/life_cycle.rb +44 -0
  115. data/app/models/workarea/segment/loyal_customer.rb +12 -0
  116. data/app/models/workarea/segment/returning_customer.rb +14 -0
  117. data/app/models/workarea/segment/returning_visitor.rb +12 -0
  118. data/app/models/workarea/segment/rules/base.rb +16 -0
  119. data/app/models/workarea/segment/rules/browser_info.rb +29 -0
  120. data/app/models/workarea/segment/rules/geolocation.rb +29 -0
  121. data/app/models/workarea/segment/rules/geolocation_option.rb +53 -0
  122. data/app/models/workarea/segment/rules/last_order.rb +14 -0
  123. data/app/models/workarea/segment/rules/logged_in.rb +13 -0
  124. data/app/models/workarea/segment/rules/orders.rb +17 -0
  125. data/app/models/workarea/segment/rules/revenue.rb +17 -0
  126. data/app/models/workarea/segment/rules/sessions.rb +17 -0
  127. data/app/models/workarea/segment/rules/tags.rb +14 -0
  128. data/app/models/workarea/segment/rules/traffic_referrer.rb +18 -0
  129. data/app/models/workarea/segment.rb +54 -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/exact_matches.rb +1 -1
  170. data/app/queries/workarea/search/storefront_search/response.rb +6 -4
  171. data/app/queries/workarea/search/storefront_search.rb +5 -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/cache.rb +6 -35
  236. data/lib/workarea/changelog.rake +2 -2
  237. data/lib/workarea/configuration/administrable/definition.rb +42 -0
  238. data/lib/workarea/configuration/administrable/field.rb +79 -0
  239. data/lib/workarea/configuration/administrable/fieldset.rb +44 -0
  240. data/lib/workarea/configuration/administrable_options.rb +24 -0
  241. data/lib/workarea/configuration/cache_store.rb +3 -1
  242. data/lib/workarea/configuration/content_blocks.rb +17 -0
  243. data/lib/workarea/configuration/mongoid.rb +1 -4
  244. data/lib/workarea/configuration/session.rb +36 -0
  245. data/lib/workarea/configuration/sidekiq.rb +3 -1
  246. data/lib/workarea/configuration.rb +121 -148
  247. data/lib/workarea/core/engine.rb +3 -58
  248. data/lib/workarea/core.rb +15 -11
  249. data/lib/workarea/elasticsearch/document.rb +8 -15
  250. data/lib/workarea/ext/freedom_patches/action_view_cache_helper.rb +4 -6
  251. data/lib/workarea/ext/freedom_patches/active_support_duration.rb +14 -0
  252. data/lib/workarea/ext/freedom_patches/money.rb +11 -0
  253. data/lib/workarea/ext/freedom_patches/premailer.rb +6 -0
  254. data/lib/workarea/ext/freedom_patches/string.rb +19 -4
  255. data/lib/workarea/ext/mongoid/find_ordered.rb +2 -2
  256. data/lib/workarea/ext/mongoid/lookup_hash.rb +30 -0
  257. data/lib/workarea/geolocation.rb +24 -6
  258. data/lib/workarea/routes_constraints/super_admin.rb +1 -1
  259. data/lib/workarea/version.rb +3 -4
  260. data/lib/workarea/visit.rb +92 -0
  261. data/lib/workarea/warnings.rb +95 -0
  262. data/lib/workarea.rb +102 -3
  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 +13 -11
  394. metadata +196 -92
  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
@@ -9,6 +9,7 @@ module Workarea
9
9
  field :error_message, type: String
10
10
  field :total, type: Integer, default: 0
11
11
  field :succeeded, type: Integer, default: 0
12
+ field :release_id, type: String
12
13
 
13
14
  # These scopes used for mailer previews only
14
15
  scope :successful, -> { where(file_errors: {}, error_type: nil, :succeeded.gt => 0) }
@@ -40,8 +41,10 @@ module Workarea
40
41
  def process!
41
42
  set(started_at: Time.current)
42
43
  assert_valid_file_type
43
- run_callbacks(:process) { format.import! }
44
44
 
45
+ Workarea::Release.with_current(release_id) do
46
+ run_callbacks(:process) { format.import! }
47
+ end
45
48
  rescue Exception => e
46
49
  self.error_type = e.class
47
50
  self.error_message = e.message
@@ -63,6 +66,11 @@ module Workarea
63
66
  end
64
67
  end
65
68
 
69
+ def releasable?
70
+ return false unless model_type.present?
71
+ model_class.new.releasable?
72
+ end
73
+
66
74
  private
67
75
 
68
76
  def set_file_type
@@ -45,31 +45,12 @@ module Workarea
45
45
 
46
46
  if id.present?
47
47
  result = model_class.find_or_initialize_by(id: id)
48
- result.attributes = attributes_without_updated_at(attributes)
48
+ result.attributes = attributes
49
49
  result
50
50
  else
51
51
  model_class.new(attributes)
52
52
  end
53
53
  end
54
-
55
- def attributes_without_updated_at(attrs)
56
- return attrs unless attrs.respond_to?(:each_with_object)
57
-
58
- attrs.each_with_object({}) do |(key, value), attributes|
59
- next if key.to_s == 'updated_at'
60
-
61
- attributes[key] = case value
62
- when Hash
63
- attributes_without_updated_at(value)
64
- when Array
65
- value.map do |item|
66
- attributes_without_updated_at(item)
67
- end
68
- else
69
- value
70
- end
71
- end
72
- end
73
54
  end
74
55
  end
75
56
  end
@@ -37,10 +37,6 @@ module Workarea
37
37
  Workarea.config.data_file_formats.first
38
38
  end
39
39
 
40
- def mime_type
41
- "#{MIME::Types.type_for(file_type).first.to_s}; charset=utf-8"
42
- end
43
-
44
40
  def process!
45
41
  raise NotImplementedError
46
42
  end
@@ -31,6 +31,9 @@ module Workarea
31
31
  country: row[:country] || 'US',
32
32
  postal_code: row[:zip_code],
33
33
  percentage: row[:estimated_combined_rate],
34
+ country_percentage: row[:federal_rate],
35
+ region_percentage: row[:state_rate],
36
+ postal_code_percentage: row[:county_rate],
34
37
  charge_on_shipping: row[:charge_on_shipping] !~ /false/i
35
38
  )
36
39
  end
@@ -6,9 +6,17 @@ module Workarea
6
6
  field :product_ids, type: Array, default: []
7
7
  before_validation :clean_product_ids
8
8
 
9
+ scope :by_product, ->(id) { self.in(product_ids: id) }
9
10
  index({ product_ids: 1 })
10
11
  end
11
12
 
13
+ def self.changesets(*product_ids)
14
+ Release::Changeset.any_of(
15
+ { 'changeset.product_ids' => { '$in' => product_ids } },
16
+ { 'original.product_ids' => { '$in' => product_ids } }
17
+ )
18
+ end
19
+
12
20
  def featured_products?
13
21
  product_ids.present?
14
22
  end
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ module Policies
4
+ class Base
5
+ attr_reader :sku
6
+
7
+ def initialize(sku)
8
+ @sku = sku
9
+ end
10
+
11
+ def requires_shipping?
12
+ false
13
+ end
14
+
15
+ def process(order_item:, fulfillment: nil)
16
+ raise(NotImplementedError)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ module Policies
4
+ class Download < Base
5
+ def process(order_item:, fulfillment: nil)
6
+ Fulfillment::Token.create!(
7
+ order_id: order_item.order.id,
8
+ order_item_id: order_item.id,
9
+ sku: sku.id
10
+ )
11
+
12
+ return unless fulfillment.present?
13
+ fulfillment.mark_item_shipped(
14
+ id: order_item.id.to_s,
15
+ quantity: order_item.quantity
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ module Policies
4
+ class Ignore < Base
5
+ def process(*args)
6
+ # no op
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ module Policies
4
+ class Ship < Base
5
+ def requires_shipping?
6
+ true
7
+ end
8
+
9
+ def process(*args)
10
+ # no op
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,72 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ class Sku
4
+ class InvalidPolicy < RuntimeError; end
5
+
6
+ include ApplicationDocument
7
+ extend Dragonfly::Model
8
+
9
+ field :_id, type: String
10
+ field :policy, type: String, default: -> { self.class.policies.first }
11
+
12
+ field :file_name, type: String
13
+ field :file_uid, type: String
14
+
15
+ dragonfly_accessor :file, app: :workarea
16
+ validates :file, presence: true, if: -> { download? }
17
+
18
+ delegate :requires_shipping?, to: :policy_object
19
+
20
+ def self.policies
21
+ Workarea.config.fulfillment_policies.map(&:demodulize).map(&:underscore)
22
+ end
23
+
24
+ def self.process!(id, **args)
25
+ find_or_initialize_by(id: id).process!(args)
26
+ end
27
+
28
+ def self.find_or_initialize_all(ids)
29
+ existing = self.in(id: ids).to_a
30
+ ids.map { |id| existing.detect { |sku| sku.id == id } || new(id: id) }
31
+ end
32
+
33
+ def name
34
+ I18n.t('workarea.fulfillment_sku.name', id: id)
35
+ end
36
+
37
+ def process!(**args)
38
+ policy_object.process(args)
39
+ end
40
+
41
+ def downloadable?
42
+ download? && file.present?
43
+ end
44
+
45
+ def method_missing(sym, *args, &block)
46
+ method = sym.to_s.chomp('?')
47
+ return super unless self.class.policies.include?(method)
48
+
49
+ method == policy
50
+ end
51
+
52
+ def respond_to_missing?(method_name, include_private = false)
53
+ self.class.policies.include?(method_name.to_s.chomp('?')) || super
54
+ end
55
+
56
+ private
57
+
58
+ def policy_object
59
+ @policy_object ||= policy_class.new(self)
60
+ end
61
+
62
+ def policy_class
63
+ "Workarea::Fulfillment::Policies::#{policy.classify}".constantize
64
+ rescue NameError
65
+ raise(
66
+ InvalidPolicy,
67
+ "Workarea::Fulfillment::Policies::#{policy.classify} must be a policy class"
68
+ )
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,36 @@
1
+ module Workarea
2
+ class Fulfillment
3
+ class Token
4
+ include ApplicationDocument
5
+
6
+ field :_id, type: String, default: -> { SecureRandom.base58(24) }
7
+ field :order_id, type: String
8
+ field :order_item_id, type: String
9
+ field :sku, type: String
10
+ field :enabled, type: Boolean, default: true
11
+ field :downloads, type: Integer, default: 0
12
+
13
+ index(order_id: 1, order_item_id: 1)
14
+ index(sku: 1)
15
+
16
+ scope :for_sku, ->(sku) { where(sku: sku) }
17
+ scope :by_order, ->(id) { where(order_id: id) }
18
+
19
+ def self.for_order_item(order_id, item_id)
20
+ where(order_id: order_id.to_s, order_item_id: item_id.to_s).first
21
+ end
22
+
23
+ def self.sorts
24
+ [Sort.newest, Sort.modified, Sort.downloads]
25
+ end
26
+
27
+ def disabled?
28
+ !enabled?
29
+ end
30
+
31
+ def from_user_order?
32
+ user_id.present? && order_id.present?
33
+ end
34
+ end
35
+ end
36
+ end
@@ -15,8 +15,7 @@ module Workarea
15
15
  validate :subject_exists
16
16
 
17
17
  def full_subject
18
- I18n.t('workarea.inquiry.subjects')[subject.optionize.to_sym].presence ||
19
- Workarea.config.inquiry_subjects[subject]
18
+ Workarea.config.inquiry_subjects[subject]
20
19
  end
21
20
 
22
21
  private
@@ -37,8 +37,8 @@ module Workarea
37
37
  {
38
38
  '$match' => {
39
39
  'first_order_at' => {
40
- '$gte' => beginning_of_last_month.utc,
41
- '$lte' => end_of_last_month.utc
40
+ '$gte' => beginning_of_last_month,
41
+ '$lte' => end_of_last_month
42
42
  }
43
43
  }
44
44
  }
@@ -48,18 +48,14 @@ module Workarea
48
48
  {
49
49
  '$group' => {
50
50
  '_id' => {
51
- 'year' => { '$year' => first_order_at_in_time_zone },
52
- 'month' => { '$month' => first_order_at_in_time_zone },
53
- 'day' => { '$dayOfMonth' => first_order_at_in_time_zone }
51
+ 'year' => { '$year' => '$first_order_at' },
52
+ 'month' => { '$month' => '$first_order_at' },
53
+ 'day' => { '$dayOfMonth' => '$first_order_at' }
54
54
  },
55
55
  'new_customers' => { '$sum' => 1 }
56
56
  }
57
57
  }
58
58
  end
59
-
60
- def first_order_at_in_time_zone
61
- { 'date' => '$first_order_at', 'timezone' => Time.zone.tzinfo.name }
62
- end
63
59
  end
64
60
  end
65
61
  end
@@ -22,8 +22,8 @@ module Workarea
22
22
  {
23
23
  '$match' => {
24
24
  'reporting_on' => {
25
- '$gte' => beginning_of_last_month.utc,
26
- '$lte' => end_of_last_month.utc
25
+ '$gte' => beginning_of_last_month,
26
+ '$lte' => end_of_last_month
27
27
  }
28
28
  }
29
29
  }
@@ -22,8 +22,8 @@ module Workarea
22
22
  {
23
23
  '$match' => {
24
24
  'reporting_on' => {
25
- '$gte' => beginning_of_last_month.utc,
26
- '$lte' => end_of_last_month.utc
25
+ '$gte' => beginning_of_last_month,
26
+ '$lte' => end_of_last_month
27
27
  }
28
28
  }
29
29
  }
@@ -14,6 +14,18 @@ module Workarea
14
14
  @records = records
15
15
  end
16
16
 
17
+ def self.statuses
18
+ Workarea.config.inventory_status_calculators.map do |klass|
19
+ klass.demodulize.underscore
20
+ end
21
+ end
22
+
23
+ statuses.each do |status_name|
24
+ define_method "#{status_name}?" do
25
+ status.to_s == status_name
26
+ end
27
+ end
28
+
17
29
  # The total number available to sell
18
30
  #
19
31
  # return [Integer]
@@ -22,6 +34,14 @@ module Workarea
22
34
  records.map(&:available_to_sell).sum
23
35
  end
24
36
 
37
+ # If the product has any puchasable inventory
38
+ #
39
+ # return [Boolean]
40
+ #
41
+ def purchasable?(quantity = 1)
42
+ quantity <= available_to_sell
43
+ end
44
+
25
45
  # Grab the specific {Sku} for a SKU.
26
46
  # Returns a new, unpersisted {Sku} if one does not exist.
27
47
  #
@@ -36,6 +56,16 @@ module Workarea
36
56
  records.map(&:policy)
37
57
  end
38
58
 
59
+ # Get the status of this collection of inventory skus.
60
+ #
61
+ # @return [Symbol]
62
+ #
63
+ def status
64
+ calculators = Workarea.config.inventory_status_calculators.map(&:constantize)
65
+ StatusCalculator.new(calculators, self).result
66
+ end
67
+
68
+
39
69
  def records
40
70
  @records ||=
41
71
  begin
@@ -0,0 +1,40 @@
1
+ module Workarea
2
+ module Inventory
3
+ module CollectionStatus
4
+ class Backordered
5
+ include StatusCalculator::Status
6
+
7
+ def in_status?
8
+ model.any?(&:allow_backorder?) &&
9
+ model.sum(&:backordered).positive? &&
10
+ model.sum(&:available).zero?
11
+ end
12
+ end
13
+
14
+ class LowInventory
15
+ include StatusCalculator::Status
16
+
17
+ def in_status?
18
+ model.purchasable? &&
19
+ !model.purchasable?(Workarea.config.low_inventory_threshold)
20
+ end
21
+ end
22
+
23
+ class OutOfStock
24
+ include StatusCalculator::Status
25
+
26
+ def in_status?
27
+ !model.purchasable?
28
+ end
29
+ end
30
+
31
+ class Available
32
+ include StatusCalculator::Status
33
+
34
+ def in_status?
35
+ model.purchasable?
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module Workarea
2
+ module Metrics
3
+ class Affinity
4
+ include ApplicationDocument
5
+
6
+ field :product_ids, type: Array, default: []
7
+ field :category_ids, type: Array, default: []
8
+ field :search_ids, type: Array, default: []
9
+
10
+ embedded_in :user, class_name: 'Workarea::Metrics::User'
11
+
12
+ def recent_product_ids(max: Workarea.config.affinity_default_recent_size, unique: false)
13
+ recent_ids(product_ids, max: max, unique: unique)
14
+ end
15
+
16
+ def recent_category_ids(max: Workarea.config.affinity_default_recent_size, unique: false)
17
+ recent_ids(category_ids, max: max, unique: unique)
18
+ end
19
+
20
+ def recent_search_ids(max: Workarea.config.affinity_default_recent_size, unique: false)
21
+ recent_ids(search_ids, max: max, unique: unique)
22
+ end
23
+
24
+ private
25
+
26
+ def recent_ids(ids, max:, unique:)
27
+ ids = ids.reverse
28
+ ids.uniq! if unique
29
+ ids.take(max)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -12,9 +12,13 @@ module Workarea
12
12
  field :discounts, type: Float, default: 0.0
13
13
  field :tax, type: Float, default: 0.0
14
14
  field :revenue, type: Float, default: 0.0
15
+ field :cancellations, type: Integer, default: 0
16
+ field :units_canceled, type: Integer, default: 0
17
+ field :refund, type: Float, default: 0.0
15
18
 
16
19
  index(reporting_on: 1, orders: 1)
17
20
  index(reporting_on: 1, units_sold: 1)
21
+ index(reporting_on: 1, units_canceled: 1)
18
22
  end
19
23
  end
20
24
  end
@@ -12,9 +12,12 @@ module Workarea
12
12
  field :discounts, type: Float, default: 0.0
13
13
  field :tax, type: Float, default: 0.0
14
14
  field :revenue, type: Float, default: 0.0
15
+ field :units_canceled, type: Integer, default: 0
16
+ field :refund, type: Float, default: 0.0
15
17
 
16
18
  index(reporting_on: 1, orders: 1)
17
19
  index(reporting_on: 1, units_sold: 1)
20
+ index(reporting_on: 1, units_canceled: 1)
18
21
  index(product_id: 1, reporting_on: 1)
19
22
  scope :by_product, ->(id) { where(product_id: id) }
20
23
  end
@@ -17,6 +17,8 @@ module Workarea
17
17
  field :average_discount, type: Float, default: 0.0
18
18
  field :discount_rate, type: Float, default: 0.0
19
19
  field :conversion_rate, type: Float, default: 0.0
20
+ field :units_canceled, type: Integer, default: 0
21
+ field :refund, type: Float, default: 0.0
20
22
 
21
23
  index(product_id: 1)
22
24
  index(views_percentile: 1, reporting_on: 1, conversion_rate: 1)
@@ -35,8 +35,8 @@ module Workarea
35
35
  {
36
36
  '$match' => {
37
37
  'reporting_on' => {
38
- '$gte' => Time.current.last_week.utc,
39
- '$lte' => Time.current.last_week.end_of_week.utc
38
+ '$gte' => Time.current.last_week,
39
+ '$lte' => Time.current.last_week.end_of_week
40
40
  }
41
41
  }
42
42
  }
@@ -54,7 +54,9 @@ module Workarea
54
54
  'discounts' => { '$sum' => '$discounts' },
55
55
  'tax' => { '$sum' => '$tax' },
56
56
  'revenue' => { '$sum' => '$revenue' },
57
- 'reporting_on' => { '$min' => '$reporting_on' }
57
+ 'reporting_on' => { '$min' => '$reporting_on' },
58
+ 'units_canceled' => { '$sum' => '$units_canceled' },
59
+ 'refund' => { '$sum' => '$refund' }
58
60
  }
59
61
  }
60
62
  end
@@ -70,8 +72,8 @@ module Workarea
70
72
  '$expr' => {
71
73
  '$and' => [
72
74
  { '$eq' => ['$product_id', '$$product_id'] },
73
- { '$gte' => ['$reporting_on', (Time.current.last_week - 1.week).utc] },
74
- { '$lte' => ['$reporting_on', (Time.current.last_week.end_of_week - 1.week).utc] }
75
+ { '$gte' => ['$reporting_on', Time.current.last_week - 1.week] },
76
+ { '$lte' => ['$reporting_on', Time.current.last_week.end_of_week - 1.week] }
75
77
  ]
76
78
  }
77
79
  }
@@ -144,13 +146,7 @@ module Workarea
144
146
  '$addFields' => {
145
147
  '_id' => {
146
148
  '$concat' => [
147
- {
148
- '$dateToString' => {
149
- 'format' => '%Y%m%d',
150
- 'date' => '$reporting_on',
151
- 'timezone' => Time.zone.tzinfo.name
152
- }
153
- },
149
+ { '$dateToString' => { 'format' => '%Y%m%d', 'date' => '$reporting_on' } },
154
150
  '-',
155
151
  '$product_id'
156
152
  ]
@@ -13,8 +13,13 @@ module Workarea
13
13
  field :discounts, type: Float, default: 0.0
14
14
  field :tax, type: Float, default: 0.0
15
15
  field :revenue, type: Float, default: 0.0
16
+ field :cancellations, type: Integer, default: 0
17
+ field :units_canceled, type: Integer, default: 0
18
+ field :refund, type: Float, default: 0.0
19
+ field :sessions, type: Integer, default: 0
16
20
 
17
21
  index(reporting_on: 1, orders: 1)
22
+ index(reporting_on: 1, cancellations: 1)
18
23
  end
19
24
  end
20
25
  end
@@ -17,13 +17,11 @@ module Workarea
17
17
  field :revenue, type: Float, default: 0.0
18
18
 
19
19
  index(reporting_on: 1, total_results: 1)
20
- index(query_id: 1)
21
-
22
20
  scope :by_query_id, ->(id) { where(query_id: id) }
23
21
 
24
22
  def self.save_search(query_string, total_results, at: Time.current)
25
23
  query_string = QueryString.new(query_string)
26
- return if query_string.id.blank? || query_string.short?
24
+ return if query_string.id.blank? || query_string.short? || total_results.blank?
27
25
 
28
26
  inc(
29
27
  key: { query_id: query_string.id },
@@ -36,8 +36,8 @@ module Workarea
36
36
  {
37
37
  '$match' => {
38
38
  'reporting_on' => {
39
- '$gte' => Time.current.last_week.utc,
40
- '$lte' => Time.current.last_week.end_of_week.utc
39
+ '$gte' => Time.current.last_week,
40
+ '$lte' => Time.current.last_week.end_of_week
41
41
  }
42
42
  }
43
43
  }
@@ -77,8 +77,8 @@ module Workarea
77
77
  '$expr' => {
78
78
  '$and' => [
79
79
  { '$eq' => ['$query_id', '$$query_id'] },
80
- { '$gte' => ['$reporting_on', (Time.current.last_week - 1.week).utc] },
81
- { '$lte' => ['$reporting_on', (Time.current.last_week.end_of_week - 1.week).utc] }
80
+ { '$gte' => ['$reporting_on', Time.current.last_week - 1.week] },
81
+ { '$lte' => ['$reporting_on', Time.current.last_week.end_of_week - 1.week] }
82
82
  ]
83
83
  }
84
84
  }
@@ -151,13 +151,7 @@ module Workarea
151
151
  '$addFields' => {
152
152
  '_id' => {
153
153
  '$concat' => [
154
- {
155
- '$dateToString' => {
156
- 'format' => '%Y%m%d',
157
- 'date' => '$reporting_on',
158
- 'timezone' => Time.zone.tzinfo.name
159
- }
160
- },
154
+ { '$dateToString' => { 'format' => '%Y%m%d', 'date' => '$reporting_on' } },
161
155
  '-',
162
156
  '$query_id'
163
157
  ]
@@ -0,0 +1,31 @@
1
+ module Workarea
2
+ module Metrics
3
+ class SegmentByDay
4
+ include ByDay
5
+
6
+ field :segment_id, type: String
7
+ field :orders, type: Integer, default: 0
8
+ field :returning_orders, type: Integer, default: 0
9
+ field :customers, type: Integer, default: 0
10
+ field :units_sold, type: Integer, default: 0
11
+ field :discounted_units_sold, type: Integer, default: 0
12
+ field :merchandise, type: Float, default: 0.0
13
+ field :shipping, type: Float, default: 0.0
14
+ field :discounts, type: Float, default: 0.0
15
+ field :tax, type: Float, default: 0.0
16
+ field :revenue, type: Float, default: 0.0
17
+ field :cancellations, type: Integer, default: 0
18
+ field :units_canceled, type: Integer, default: 0
19
+ field :refund, type: Float, default: 0.0
20
+ field :sessions, type: Integer, default: 0
21
+
22
+ index(segment_id: 1, reporting_on: 1)
23
+ scope :by_segment, ->(id) { where(segment_id: id) }
24
+
25
+ def average_order_value
26
+ return nil if orders.zero?
27
+ revenue / orders.to_f
28
+ end
29
+ end
30
+ end
31
+ end