workarea 3.4.16 → 3.4.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (572) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. metadata +10 -579
  4. data/docs/Gemfile +0 -8
  5. data/docs/Gemfile.lock +0 -130
  6. data/docs/bin/middleman +0 -29
  7. data/docs/config.rb +0 -87
  8. data/docs/config.ru +0 -7
  9. data/docs/data/articles.yml +0 -157
  10. data/docs/package.json +0 -15
  11. data/docs/source/404.html.erb +0 -13
  12. data/docs/source/articles/access-routes-in-javascript.html.md +0 -33
  13. data/docs/source/articles/add-a-content-area.html.md +0 -169
  14. data/docs/source/articles/add-a-content-block-type.html.md +0 -334
  15. data/docs/source/articles/add-a-report.html.md +0 -202
  16. data/docs/source/articles/add-css-through-the-admin-ui.html.md +0 -30
  17. data/docs/source/articles/add-javascript-through-a-manifest.html.md +0 -367
  18. data/docs/source/articles/add-javascript-through-a-view.html.md +0 -80
  19. data/docs/source/articles/add-javascript-through-the-admin-ui.html.md +0 -30
  20. data/docs/source/articles/add-metrics.html.md +0 -58
  21. data/docs/source/articles/add-or-replace-a-pricing-calculator.html.md +0 -150
  22. data/docs/source/articles/add-remove-or-change-a-mongoid-validation.html.md +0 -147
  23. data/docs/source/articles/add-remove-or-change-a-product-template.html.md +0 -142
  24. data/docs/source/articles/add-remove-sort-and-group-storefront-search-filters.html.md +0 -483
  25. data/docs/source/articles/add-stylesheets-through-a-manifest.html.md +0 -276
  26. data/docs/source/articles/add-system-content.html.md +0 -138
  27. data/docs/source/articles/analytics-overview.html.md +0 -51
  28. data/docs/source/articles/analyze-storefront-search-results.html.md +0 -261
  29. data/docs/source/articles/api-overview.html.md +0 -35
  30. data/docs/source/articles/appending.html.md +0 -506
  31. data/docs/source/articles/application-document.html.md +0 -88
  32. data/docs/source/articles/automated-javascript-testing.html.md +0 -162
  33. data/docs/source/articles/b2b-overview.html.md +0 -64
  34. data/docs/source/articles/browser-and-device-support.html.md +0 -47
  35. data/docs/source/articles/change-product-placeholder-image.html.md +0 -39
  36. data/docs/source/articles/change-storefront-search-results.html.md +0 -283
  37. data/docs/source/articles/change-the-storefront-product-pricing-ui.html.md +0 -348
  38. data/docs/source/articles/change-the-storefront-search-filters-ui.html.md +0 -103
  39. data/docs/source/articles/checkout.html.md +0 -479
  40. data/docs/source/articles/commerce-model.html.md +0 -164
  41. data/docs/source/articles/configuration-for-hosting.html.md +0 -106
  42. data/docs/source/articles/configuration.html.md +0 -406
  43. data/docs/source/articles/configure-a-payment-gateway.html.md +0 -58
  44. data/docs/source/articles/configure-asset-storage.html.md +0 -29
  45. data/docs/source/articles/configure-asset-types.html.md +0 -18
  46. data/docs/source/articles/configure-contact-form-subjects-list.html.md +0 -24
  47. data/docs/source/articles/configure-imageoptim.html.md +0 -23
  48. data/docs/source/articles/configure-locales.html.md +0 -45
  49. data/docs/source/articles/configure-logins-and-authentication.html.md +0 -42
  50. data/docs/source/articles/configure-low-inventory-threshold.html.md +0 -26
  51. data/docs/source/articles/configure-product-image-sizes-and-processing.html.md +0 -28
  52. data/docs/source/articles/content.html.md +0 -554
  53. data/docs/source/articles/contentable.html.md +0 -41
  54. data/docs/source/articles/contribute-code.html.md +0 -69
  55. data/docs/source/articles/contribute-documentation.html.md +0 -60
  56. data/docs/source/articles/create-a-custom-discount.html.md +0 -234
  57. data/docs/source/articles/create-a-new-app.html.md +0 -131
  58. data/docs/source/articles/create-a-plugin.html.md +0 -19
  59. data/docs/source/articles/create-a-style-guide.html.md +0 -71
  60. data/docs/source/articles/create-a-theme.html.md +0 -134
  61. data/docs/source/articles/css-architectural-overview.html.md +0 -89
  62. data/docs/source/articles/customize-a-helper.html.md +0 -91
  63. data/docs/source/articles/decoration.html.md +0 -415
  64. data/docs/source/articles/define-and-configure-inventory-policies.html.md +0 -107
  65. data/docs/source/articles/documentation-style-guide.html.md +0 -48
  66. data/docs/source/articles/documentation.html.md +0 -54
  67. data/docs/source/articles/domain-modeling.html.md +0 -82
  68. data/docs/source/articles/error-pages.html.md.erb +0 -95
  69. data/docs/source/articles/extension-overview.html.md +0 -152
  70. data/docs/source/articles/favicon-support.html.md +0 -112
  71. data/docs/source/articles/feature-spec-helper-stylesheet.html.md +0 -25
  72. data/docs/source/articles/featurejs-and-feature-spec-helper.html.md +0 -20
  73. data/docs/source/articles/help-and-support.html.md +0 -34
  74. data/docs/source/articles/html-fragment-caching.html.md +0 -46
  75. data/docs/source/articles/http-caching.html.md +0 -43
  76. data/docs/source/articles/i18n.html.md +0 -35
  77. data/docs/source/articles/images-flow.html.md +0 -10
  78. data/docs/source/articles/index-storefront-search-documents.html.md +0 -104
  79. data/docs/source/articles/infrastructure.html.md +0 -46
  80. data/docs/source/articles/installing.html.md +0 -61
  81. data/docs/source/articles/integrate-a-payment-gateway.html.md +0 -124
  82. data/docs/source/articles/integrate-a-web-analytics-provider.html.md +0 -35
  83. data/docs/source/articles/integrate-an-inventory-management-system.html.md +0 -88
  84. data/docs/source/articles/integrating-with-other-software.html.md +0 -59
  85. data/docs/source/articles/inventory.html.md +0 -352
  86. data/docs/source/articles/javascript-coding-standards.html.md +0 -30
  87. data/docs/source/articles/javascript-modules.html.md +0 -174
  88. data/docs/source/articles/javascript-overview.html.md +0 -62
  89. data/docs/source/articles/javascript-reference-documentation.html.md +0 -51
  90. data/docs/source/articles/javascript-templates.html.md +0 -52
  91. data/docs/source/articles/low-level-caching.html.md +0 -25
  92. data/docs/source/articles/maintain-a-plugin.html.md +0 -12
  93. data/docs/source/articles/maintenance-policy.html.md +0 -79
  94. data/docs/source/articles/navigable.html.md +0 -51
  95. data/docs/source/articles/navigating-the-code.html.md +0 -149
  96. data/docs/source/articles/navigation.html.md +0 -386
  97. data/docs/source/articles/order-life-cycle.html.md +0 -546
  98. data/docs/source/articles/order-pricing.html.md +0 -389
  99. data/docs/source/articles/orders-and-items.html.md +0 -210
  100. data/docs/source/articles/orders.html.md +0 -66
  101. data/docs/source/articles/overriding.html.md +0 -155
  102. data/docs/source/articles/overview.html.md +0 -43
  103. data/docs/source/articles/plugins-overview.html.md +0 -12
  104. data/docs/source/articles/prerequisites-and-dependencies.html.md +0 -202
  105. data/docs/source/articles/products.html.md.erb +0 -1270
  106. data/docs/source/articles/progressive-web-application-support.html.md +0 -148
  107. data/docs/source/articles/rails-asset-manifests.html.md +0 -33
  108. data/docs/source/articles/rails-asset-view-helpers.html.md +0 -25
  109. data/docs/source/articles/reading-data.html.md +0 -10
  110. data/docs/source/articles/releasable.html.md +0 -37
  111. data/docs/source/articles/report-a-bug.html.md +0 -75
  112. data/docs/source/articles/ruby-coding-standards.html.md +0 -10
  113. data/docs/source/articles/run-sidekiq-in-a-local-environment.html.md +0 -40
  114. data/docs/source/articles/searching.html.md +0 -1005
  115. data/docs/source/articles/security-policy.html.md +0 -42
  116. data/docs/source/articles/seeds.html.md +0 -345
  117. data/docs/source/articles/shipping.html.md +0 -756
  118. data/docs/source/articles/sort-and-exclude-product-options.html.md +0 -47
  119. data/docs/source/articles/storefront-search-features.html.md +0 -568
  120. data/docs/source/articles/storefront-searches.html.md +0 -126
  121. data/docs/source/articles/style-guides.html.md +0 -21
  122. data/docs/source/articles/stylesheet-coding-standards.html.md +0 -24
  123. data/docs/source/articles/stylesheets-overview.html.md +0 -67
  124. data/docs/source/articles/swappable-list-data-structure.html.md +0 -81
  125. data/docs/source/articles/system-emails.html.md +0 -102
  126. data/docs/source/articles/taggable.html.md +0 -8
  127. data/docs/source/articles/test-a-credit-card-transaction.html.md +0 -16
  128. data/docs/source/articles/test-if-a-plugin-is-installed.html.md +0 -34
  129. data/docs/source/articles/testing.html.md +0 -914
  130. data/docs/source/articles/themes-overview.html.md +0 -155
  131. data/docs/source/articles/translate-administrable-content.html.md +0 -14
  132. data/docs/source/articles/translate-javascript-content.html.md +0 -16
  133. data/docs/source/articles/translate-or-customize-message-content.html.md +0 -29
  134. data/docs/source/articles/translate-or-customize-static-content.html.md +0 -30
  135. data/docs/source/articles/use-an-existing-workarea-app.html.md +0 -108
  136. data/docs/source/articles/view-models.html.md +0 -509
  137. data/docs/source/articles/views.html.md +0 -14
  138. data/docs/source/articles/workers.html.md +0 -613
  139. data/docs/source/articles/writing-data.html.md +0 -10
  140. data/docs/source/cli.html.md +0 -163
  141. data/docs/source/favicon.ico +0 -0
  142. data/docs/source/images/3-variants-1-option.png +0 -0
  143. data/docs/source/images/3-variants-3-options.png +0 -0
  144. data/docs/source/images/3-years-primary-image.png +0 -0
  145. data/docs/source/images/404-storefront-error-page.png +0 -0
  146. data/docs/source/images/404-system-content-admin.png +0 -0
  147. data/docs/source/images/404.jpg +0 -0
  148. data/docs/source/images/5-years-primary-image.png +0 -0
  149. data/docs/source/images/activity-dashboard.png +0 -0
  150. data/docs/source/images/activity-for-object.png +0 -0
  151. data/docs/source/images/activity-ui.png +0 -0
  152. data/docs/source/images/adding-captioned-image-block-custom-icon.png +0 -0
  153. data/docs/source/images/adding-captioned-image-block-default-icon.png +0 -0
  154. data/docs/source/images/admin-alerts-ui.png +0 -0
  155. data/docs/source/images/admin-category-range-filters.png +0 -0
  156. data/docs/source/images/admin-for-3-column-hero.png +0 -0
  157. data/docs/source/images/admin-help-index.png +0 -0
  158. data/docs/source/images/admin-help-ui.png +0 -0
  159. data/docs/source/images/admin-javascript.png +0 -0
  160. data/docs/source/images/admin-notification-for-deactivated-discount.png +0 -0
  161. data/docs/source/images/admin-notifications-ui.png +0 -0
  162. data/docs/source/images/admin-product-show-page.png +0 -0
  163. data/docs/source/images/admin-products-index-page.png +0 -0
  164. data/docs/source/images/admin-range-filters.png +0 -0
  165. data/docs/source/images/admin-style-guides-navigation.png +0 -0
  166. data/docs/source/images/after-re-seeding.png +0 -0
  167. data/docs/source/images/after-seeding-localhost-3000.png +0 -0
  168. data/docs/source/images/after-seeding.png +0 -0
  169. data/docs/source/images/arrow.svg +0 -1
  170. data/docs/source/images/arrow_white.svg +0 -1
  171. data/docs/source/images/aws-resource-map.png +0 -0
  172. data/docs/source/images/backordered-until-output-on-inventory-sku-card.png +0 -0
  173. data/docs/source/images/before-seeding-localhost-3000.png +0 -0
  174. data/docs/source/images/before-seeding.png +0 -0
  175. data/docs/source/images/browsing-workarea-versions-on-the-web.png +0 -0
  176. data/docs/source/images/bulk-asset-upload-on-assets-index-page.png +0 -0
  177. data/docs/source/images/bulk-asset-upload-while-editing-content.png +0 -0
  178. data/docs/source/images/bundle-show-workarea-core.png +0 -0
  179. data/docs/source/images/bundle-show-workarea.png +0 -0
  180. data/docs/source/images/calendar-for-backordered-until-field.png +0 -0
  181. data/docs/source/images/captioned-image-block-in-storefront.png +0 -0
  182. data/docs/source/images/captioned-image-content-block-storefront-component-style-guide.png +0 -0
  183. data/docs/source/images/cart-system-content-in-admin.png +0 -0
  184. data/docs/source/images/cart-system-content-in-storefront.png +0 -0
  185. data/docs/source/images/checkout-addresses-guest.png +0 -0
  186. data/docs/source/images/checkout-addresses-user.png +0 -0
  187. data/docs/source/images/checkout-confirmation.png +0 -0
  188. data/docs/source/images/checkout-flow-0.png +0 -0
  189. data/docs/source/images/checkout-flow-1.png +0 -0
  190. data/docs/source/images/checkout-flow-2.png +0 -0
  191. data/docs/source/images/checkout-flow-3.png +0 -0
  192. data/docs/source/images/checkout-flow-4.png +0 -0
  193. data/docs/source/images/checkout-payment-guest.png +0 -0
  194. data/docs/source/images/checkout-payment-user.png +0 -0
  195. data/docs/source/images/checkout-shipping.png +0 -0
  196. data/docs/source/images/color-picker-component-admin-style-guide.png +0 -0
  197. data/docs/source/images/color-picker-component-on-content-editing-screen.png +0 -0
  198. data/docs/source/images/commerce-model-carts-orders.png +0 -0
  199. data/docs/source/images/commerce-model-order-pricing.png +0 -0
  200. data/docs/source/images/commerce-model.png +0 -0
  201. data/docs/source/images/configuring-an-index-pattern-in-kibana.png +0 -0
  202. data/docs/source/images/content-block-presets.png +0 -0
  203. data/docs/source/images/content-search-customization.png +0 -0
  204. data/docs/source/images/country-with-region-data-in-address-form.png +0 -0
  205. data/docs/source/images/country-without-region-data-in-address-form.png +0 -0
  206. data/docs/source/images/create-content-block-preset-ui.png +0 -0
  207. data/docs/source/images/credit-card-icons.png +0 -0
  208. data/docs/source/images/css-added-through-admin.png +0 -0
  209. data/docs/source/images/css-admin-ui.png +0 -0
  210. data/docs/source/images/current-configuration-shown-in-admin-settings.png +0 -0
  211. data/docs/source/images/customer-impersonation-in-admin.png +0 -0
  212. data/docs/source/images/customer-impersonation-in-store-front.png +0 -0
  213. data/docs/source/images/date-filter-same-day.png +0 -0
  214. data/docs/source/images/developer-toolbar-in-store-front.png +0 -0
  215. data/docs/source/images/discounts-sorted-by-most-redeemed.png +0 -0
  216. data/docs/source/images/edit-help-article.png +0 -0
  217. data/docs/source/images/editing-content-for-search-customization.png +0 -0
  218. data/docs/source/images/editing-dynamic-captioned-image-block.png +0 -0
  219. data/docs/source/images/editing-product-fields-in-the-admin.png +0 -0
  220. data/docs/source/images/editing-search-system-content.png +0 -0
  221. data/docs/source/images/editing-static-captioned-image-block-custom-icon.png +0 -0
  222. data/docs/source/images/editing-static-captioned-image-block-default-icon.png +0 -0
  223. data/docs/source/images/external.svg +0 -1
  224. data/docs/source/images/favicon_16.png +0 -0
  225. data/docs/source/images/favicon_180.png +0 -0
  226. data/docs/source/images/favicon_32.png +0 -0
  227. data/docs/source/images/filters-all.png +0 -0
  228. data/docs/source/images/filters-control.png +0 -0
  229. data/docs/source/images/filters-custom.png +0 -0
  230. data/docs/source/images/filters-groups.png +0 -0
  231. data/docs/source/images/filters-material.png +0 -0
  232. data/docs/source/images/filters-omitted.png +0 -0
  233. data/docs/source/images/filters-pinned.png +0 -0
  234. data/docs/source/images/filters-range.png +0 -0
  235. data/docs/source/images/filters-sorted.png +0 -0
  236. data/docs/source/images/filters-wrapping-to-second-line-in-admin.png +0 -0
  237. data/docs/source/images/generic-product-template-images-no-options-selected.png +0 -0
  238. data/docs/source/images/generic-product-template-images-options-selected.png +0 -0
  239. data/docs/source/images/generic-template.png +0 -0
  240. data/docs/source/images/hosting.svg +0 -1
  241. data/docs/source/images/image-group-content-block-in-storefront.png +0 -0
  242. data/docs/source/images/images.svg +0 -1
  243. data/docs/source/images/import-export-screenshot.png +0 -0
  244. data/docs/source/images/invalid-display.png +0 -0
  245. data/docs/source/images/itcss.png +0 -0
  246. data/docs/source/images/kibana-dev-tools-console.png +0 -0
  247. data/docs/source/images/layout-content-admin-with-2-areas.png +0 -0
  248. data/docs/source/images/layout-content-admin-with-3-areas.png +0 -0
  249. data/docs/source/images/link-to-search-system-content.png +0 -0
  250. data/docs/source/images/logo.svg +0 -1
  251. data/docs/source/images/menu.svg +0 -2
  252. data/docs/source/images/mongo-replica-set.svg +0 -1
  253. data/docs/source/images/multi-column-hero-blocks.png +0 -0
  254. data/docs/source/images/option-selects-product-template-images-options-selected.png +0 -0
  255. data/docs/source/images/option-selects-template.png +0 -0
  256. data/docs/source/images/option-thumbnails-template.png +0 -0
  257. data/docs/source/images/order-item-total-price-diagram.png +0 -0
  258. data/docs/source/images/order-pricing-cart-example.png +0 -0
  259. data/docs/source/images/order-pricing-example-adjustments.png +0 -0
  260. data/docs/source/images/order-pricing-example-totals.png +0 -0
  261. data/docs/source/images/order-pricing-placed-order-example.png +0 -0
  262. data/docs/source/images/order-shipping-total-diagram.png +0 -0
  263. data/docs/source/images/order-show-with-multiple-tenders.png +0 -0
  264. data/docs/source/images/order-subtotal-price-diagram.png +0 -0
  265. data/docs/source/images/order-tax-total-diagram.png +0 -0
  266. data/docs/source/images/order-total-price-diagram.png +0 -0
  267. data/docs/source/images/order-total-value-diagram.png +0 -0
  268. data/docs/source/images/orders-dashboard-links.png +0 -0
  269. data/docs/source/images/oval.svg +0 -1
  270. data/docs/source/images/payment-icon-storefront-style-guide.png +0 -0
  271. data/docs/source/images/people-dashboard-links.png +0 -0
  272. data/docs/source/images/price-adjustments-diagram.png +0 -0
  273. data/docs/source/images/price-display-no-options.png +0 -0
  274. data/docs/source/images/price-display-options-selected.png +0 -0
  275. data/docs/source/images/pricing-calculators-diagram.png +0 -0
  276. data/docs/source/images/product-list-content-block-admin.png +0 -0
  277. data/docs/source/images/product-list-content-block-in-store-front.png +0 -0
  278. data/docs/source/images/promo-products-excluded-autocomplete-results-after.png +0 -0
  279. data/docs/source/images/promo-products-excluded-featured-category-results-after.png +0 -0
  280. data/docs/source/images/promo-products-excluded-recommendations-results-after.png +0 -0
  281. data/docs/source/images/promo-products-excluded-search-category-results-after.png +0 -0
  282. data/docs/source/images/promo-products-excluded-search-results-after.png +0 -0
  283. data/docs/source/images/promo-products-included-autocomplete-results-before.png +0 -0
  284. data/docs/source/images/promo-products-included-featured-category-results-before.png +0 -0
  285. data/docs/source/images/promo-products-included-recommendations-results-before.png +0 -0
  286. data/docs/source/images/promo-products-included-search-category-results-before.png +0 -0
  287. data/docs/source/images/promo-products-included-search-results-before.png +0 -0
  288. data/docs/source/images/rails-version-constraint.png +0 -0
  289. data/docs/source/images/re-enable-discount.png +0 -0
  290. data/docs/source/images/reading-data.svg +0 -1
  291. data/docs/source/images/readme-hero.png +0 -0
  292. data/docs/source/images/redesigned-customized-sort-for-search-results.png +0 -0
  293. data/docs/source/images/reviews-summary-above-share-buttons.png +0 -0
  294. data/docs/source/images/reviews-summary-below-product-name.png +0 -0
  295. data/docs/source/images/reviews-summary-below-share-buttons.png +0 -0
  296. data/docs/source/images/reviews-summary-removed.png +0 -0
  297. data/docs/source/images/rsa-fingerprint-for-stash.png +0 -0
  298. data/docs/source/images/ruby-version-constraint.png +0 -0
  299. data/docs/source/images/script-tag-added-through-admin.png +0 -0
  300. data/docs/source/images/search-analysis-admin-alternate-rendering.png +0 -0
  301. data/docs/source/images/search-analysis-admin.png +0 -0
  302. data/docs/source/images/search-quality-report.png +0 -0
  303. data/docs/source/images/search.svg +0 -1
  304. data/docs/source/images/searching-for-cart-system-content-in-admin.png +0 -0
  305. data/docs/source/images/searching-for-layout-system-content-in-admin.png +0 -0
  306. data/docs/source/images/seeded-admin.png +0 -0
  307. data/docs/source/images/seeds-from-plugins.png +0 -0
  308. data/docs/source/images/seo-metadata-automation-ui.png +0 -0
  309. data/docs/source/images/show-password-button.png +0 -0
  310. data/docs/source/images/storefront-autocomplete.png +0 -0
  311. data/docs/source/images/storefront-category-summary-content-block.png +0 -0
  312. data/docs/source/images/storefront-category.png +0 -0
  313. data/docs/source/images/storefront-product-after-overriding.png +0 -0
  314. data/docs/source/images/storefront-product-before-overriding.png +0 -0
  315. data/docs/source/images/storefront-product-browse-page.png +0 -0
  316. data/docs/source/images/storefront-product-recommendations.png +0 -0
  317. data/docs/source/images/storefront-product-show-page.png +0 -0
  318. data/docs/source/images/storefront-requests-and-search-requests.png +0 -0
  319. data/docs/source/images/storefront-search-request-handling.png +0 -0
  320. data/docs/source/images/storefront-search-response-creation.png +0 -0
  321. data/docs/source/images/storefront-search.png +0 -0
  322. data/docs/source/images/storefront-style-guides-navigation.png +0 -0
  323. data/docs/source/images/styles.css +0 -3
  324. data/docs/source/images/tax-categories-ui.png +0 -0
  325. data/docs/source/images/tax-rates-ui.png +0 -0
  326. data/docs/source/images/unpurchasable-product.png +0 -0
  327. data/docs/source/images/url-redirects-filtering.png +0 -0
  328. data/docs/source/images/utility-nav-area-in-admin.png +0 -0
  329. data/docs/source/images/utility-nav-area-in-storefront.png +0 -0
  330. data/docs/source/images/validation-message-in-storefront.png +0 -0
  331. data/docs/source/images/view-model-interface.png +0 -0
  332. data/docs/source/images/viewing-workarea-version-in-source.png +0 -0
  333. data/docs/source/images/workarea.svg +0 -1
  334. data/docs/source/images/worst-performing-searches-on-results-customization-page.png +0 -0
  335. data/docs/source/images/writing-data.svg +0 -1
  336. data/docs/source/index.html.erb +0 -166
  337. data/docs/source/javascripts/jquery.js +0 -2
  338. data/docs/source/javascripts/lunr.js +0 -7
  339. data/docs/source/javascripts/site.js +0 -299
  340. data/docs/source/javascripts/vendor/highlight.pack.js +0 -2
  341. data/docs/source/layouts/article.erb +0 -106
  342. data/docs/source/layouts/bare.erb +0 -46
  343. data/docs/source/layouts/layout.erb +0 -43
  344. data/docs/source/release-notes/workarea-3-0-0.html.md +0 -146
  345. data/docs/source/release-notes/workarea-3-0-1.html.md +0 -161
  346. data/docs/source/release-notes/workarea-3-0-10.html.md +0 -39
  347. data/docs/source/release-notes/workarea-3-0-11.html.md +0 -277
  348. data/docs/source/release-notes/workarea-3-0-12.html.md +0 -14
  349. data/docs/source/release-notes/workarea-3-0-13.html.md +0 -153
  350. data/docs/source/release-notes/workarea-3-0-14.html.md +0 -93
  351. data/docs/source/release-notes/workarea-3-0-15.html.md +0 -107
  352. data/docs/source/release-notes/workarea-3-0-16.html.md +0 -36
  353. data/docs/source/release-notes/workarea-3-0-17.html.md +0 -141
  354. data/docs/source/release-notes/workarea-3-0-18.html.md +0 -123
  355. data/docs/source/release-notes/workarea-3-0-19.html.md +0 -160
  356. data/docs/source/release-notes/workarea-3-0-2.html.md +0 -222
  357. data/docs/source/release-notes/workarea-3-0-20.html.md +0 -95
  358. data/docs/source/release-notes/workarea-3-0-21.html.md +0 -168
  359. data/docs/source/release-notes/workarea-3-0-22.html.md +0 -268
  360. data/docs/source/release-notes/workarea-3-0-23.html.md +0 -173
  361. data/docs/source/release-notes/workarea-3-0-24.html.md +0 -19
  362. data/docs/source/release-notes/workarea-3-0-25.html.md +0 -26
  363. data/docs/source/release-notes/workarea-3-0-26.html.md +0 -199
  364. data/docs/source/release-notes/workarea-3-0-27.html.md +0 -113
  365. data/docs/source/release-notes/workarea-3-0-28.html.md +0 -39
  366. data/docs/source/release-notes/workarea-3-0-29.html.md +0 -73
  367. data/docs/source/release-notes/workarea-3-0-3.html.md +0 -35
  368. data/docs/source/release-notes/workarea-3-0-30.html.md +0 -186
  369. data/docs/source/release-notes/workarea-3-0-31.html.md +0 -125
  370. data/docs/source/release-notes/workarea-3-0-32.html.md +0 -73
  371. data/docs/source/release-notes/workarea-3-0-33.html.md +0 -137
  372. data/docs/source/release-notes/workarea-3-0-34.html.md +0 -203
  373. data/docs/source/release-notes/workarea-3-0-35.html.md +0 -205
  374. data/docs/source/release-notes/workarea-3-0-36.html.md +0 -105
  375. data/docs/source/release-notes/workarea-3-0-37.html.md +0 -144
  376. data/docs/source/release-notes/workarea-3-0-38.html.md +0 -73
  377. data/docs/source/release-notes/workarea-3-0-39.html.md +0 -77
  378. data/docs/source/release-notes/workarea-3-0-4.html.md +0 -14
  379. data/docs/source/release-notes/workarea-3-0-40.html.md +0 -130
  380. data/docs/source/release-notes/workarea-3-0-41.html.md +0 -70
  381. data/docs/source/release-notes/workarea-3-0-42.html.md +0 -52
  382. data/docs/source/release-notes/workarea-3-0-43.html.md +0 -72
  383. data/docs/source/release-notes/workarea-3-0-44.html.md +0 -93
  384. data/docs/source/release-notes/workarea-3-0-45.html.md +0 -61
  385. data/docs/source/release-notes/workarea-3-0-46.html.md +0 -171
  386. data/docs/source/release-notes/workarea-3-0-47.html.md +0 -130
  387. data/docs/source/release-notes/workarea-3-0-48.html.md +0 -160
  388. data/docs/source/release-notes/workarea-3-0-49.html.md +0 -28
  389. data/docs/source/release-notes/workarea-3-0-5.html.md +0 -225
  390. data/docs/source/release-notes/workarea-3-0-50.html.md +0 -74
  391. data/docs/source/release-notes/workarea-3-0-51.html.md +0 -61
  392. data/docs/source/release-notes/workarea-3-0-52.html.md +0 -76
  393. data/docs/source/release-notes/workarea-3-0-53.html.md +0 -126
  394. data/docs/source/release-notes/workarea-3-0-54.html.md +0 -112
  395. data/docs/source/release-notes/workarea-3-0-55.html.md +0 -105
  396. data/docs/source/release-notes/workarea-3-0-56.html.md +0 -56
  397. data/docs/source/release-notes/workarea-3-0-57.html.md +0 -82
  398. data/docs/source/release-notes/workarea-3-0-58.html.md +0 -153
  399. data/docs/source/release-notes/workarea-3-0-59.html.md +0 -78
  400. data/docs/source/release-notes/workarea-3-0-6.html.md +0 -165
  401. data/docs/source/release-notes/workarea-3-0-60.html.md +0 -43
  402. data/docs/source/release-notes/workarea-3-0-61.html.md +0 -46
  403. data/docs/source/release-notes/workarea-3-0-62.html.md +0 -23
  404. data/docs/source/release-notes/workarea-3-0-63.html.md +0 -25
  405. data/docs/source/release-notes/workarea-3-0-64.html.md +0 -25
  406. data/docs/source/release-notes/workarea-3-0-65.html.md +0 -37
  407. data/docs/source/release-notes/workarea-3-0-7.html.md +0 -207
  408. data/docs/source/release-notes/workarea-3-0-8.html.md +0 -337
  409. data/docs/source/release-notes/workarea-3-0-9.html.md +0 -196
  410. data/docs/source/release-notes/workarea-3-1-0.html.md +0 -414
  411. data/docs/source/release-notes/workarea-3-1-1.html.md +0 -139
  412. data/docs/source/release-notes/workarea-3-1-10.html.md +0 -19
  413. data/docs/source/release-notes/workarea-3-1-11.html.md +0 -27
  414. data/docs/source/release-notes/workarea-3-1-12.html.md +0 -216
  415. data/docs/source/release-notes/workarea-3-1-13.html.md +0 -113
  416. data/docs/source/release-notes/workarea-3-1-14.html.md +0 -39
  417. data/docs/source/release-notes/workarea-3-1-15.html.md +0 -107
  418. data/docs/source/release-notes/workarea-3-1-16.html.md +0 -188
  419. data/docs/source/release-notes/workarea-3-1-17.html.md +0 -141
  420. data/docs/source/release-notes/workarea-3-1-18.html.md +0 -73
  421. data/docs/source/release-notes/workarea-3-1-19.html.md +0 -137
  422. data/docs/source/release-notes/workarea-3-1-2.html.md +0 -55
  423. data/docs/source/release-notes/workarea-3-1-20.html.md +0 -203
  424. data/docs/source/release-notes/workarea-3-1-21.html.md +0 -205
  425. data/docs/source/release-notes/workarea-3-1-22.html.md +0 -121
  426. data/docs/source/release-notes/workarea-3-1-23.html.md +0 -144
  427. data/docs/source/release-notes/workarea-3-1-24.html.md +0 -94
  428. data/docs/source/release-notes/workarea-3-1-25.html.md +0 -77
  429. data/docs/source/release-notes/workarea-3-1-26.html.md +0 -130
  430. data/docs/source/release-notes/workarea-3-1-27.html.md +0 -70
  431. data/docs/source/release-notes/workarea-3-1-28.html.md +0 -52
  432. data/docs/source/release-notes/workarea-3-1-29.html.md +0 -44
  433. data/docs/source/release-notes/workarea-3-1-3.html.md +0 -185
  434. data/docs/source/release-notes/workarea-3-1-30.html.md +0 -72
  435. data/docs/source/release-notes/workarea-3-1-31.html.md +0 -93
  436. data/docs/source/release-notes/workarea-3-1-32.html.md +0 -61
  437. data/docs/source/release-notes/workarea-3-1-33.html.md +0 -171
  438. data/docs/source/release-notes/workarea-3-1-34.html.md +0 -130
  439. data/docs/source/release-notes/workarea-3-1-35.html.md +0 -179
  440. data/docs/source/release-notes/workarea-3-1-36.html.md +0 -28
  441. data/docs/source/release-notes/workarea-3-1-37.html.md +0 -74
  442. data/docs/source/release-notes/workarea-3-1-38.html.md +0 -61
  443. data/docs/source/release-notes/workarea-3-1-39.html.md +0 -96
  444. data/docs/source/release-notes/workarea-3-1-4.html.md +0 -148
  445. data/docs/source/release-notes/workarea-3-1-40.html.md +0 -126
  446. data/docs/source/release-notes/workarea-3-1-41.html.md +0 -128
  447. data/docs/source/release-notes/workarea-3-1-42.html.md +0 -105
  448. data/docs/source/release-notes/workarea-3-1-43.html.md +0 -37
  449. data/docs/source/release-notes/workarea-3-1-44.html.md +0 -82
  450. data/docs/source/release-notes/workarea-3-1-45.html.md +0 -153
  451. data/docs/source/release-notes/workarea-3-1-46.html.md +0 -91
  452. data/docs/source/release-notes/workarea-3-1-47.html.md +0 -65
  453. data/docs/source/release-notes/workarea-3-1-48.html.md +0 -46
  454. data/docs/source/release-notes/workarea-3-1-49.html.md +0 -23
  455. data/docs/source/release-notes/workarea-3-1-5.html.md +0 -169
  456. data/docs/source/release-notes/workarea-3-1-50.html.md +0 -42
  457. data/docs/source/release-notes/workarea-3-1-51.html.md +0 -25
  458. data/docs/source/release-notes/workarea-3-1-52.html.md +0 -57
  459. data/docs/source/release-notes/workarea-3-1-6.html.md +0 -117
  460. data/docs/source/release-notes/workarea-3-1-7.html.md +0 -176
  461. data/docs/source/release-notes/workarea-3-1-8.html.md +0 -283
  462. data/docs/source/release-notes/workarea-3-1-9.html.md +0 -212
  463. data/docs/source/release-notes/workarea-3-2-0.html.md +0 -1705
  464. data/docs/source/release-notes/workarea-3-2-1.html.md +0 -216
  465. data/docs/source/release-notes/workarea-3-2-10.html.md +0 -237
  466. data/docs/source/release-notes/workarea-3-2-11.html.md +0 -121
  467. data/docs/source/release-notes/workarea-3-2-12.html.md +0 -145
  468. data/docs/source/release-notes/workarea-3-2-13.html.md +0 -138
  469. data/docs/source/release-notes/workarea-3-2-14.html.md +0 -77
  470. data/docs/source/release-notes/workarea-3-2-15.html.md +0 -130
  471. data/docs/source/release-notes/workarea-3-2-16.html.md +0 -111
  472. data/docs/source/release-notes/workarea-3-2-17.html.md +0 -52
  473. data/docs/source/release-notes/workarea-3-2-18.html.md +0 -44
  474. data/docs/source/release-notes/workarea-3-2-19.html.md +0 -72
  475. data/docs/source/release-notes/workarea-3-2-2.html.md +0 -145
  476. data/docs/source/release-notes/workarea-3-2-20.html.md +0 -93
  477. data/docs/source/release-notes/workarea-3-2-21.html.md +0 -61
  478. data/docs/source/release-notes/workarea-3-2-22.html.md +0 -154
  479. data/docs/source/release-notes/workarea-3-2-23.html.md +0 -130
  480. data/docs/source/release-notes/workarea-3-2-24.html.md +0 -200
  481. data/docs/source/release-notes/workarea-3-2-25.html.md +0 -28
  482. data/docs/source/release-notes/workarea-3-2-26.html.md +0 -94
  483. data/docs/source/release-notes/workarea-3-2-27.html.md +0 -61
  484. data/docs/source/release-notes/workarea-3-2-28.html.md +0 -96
  485. data/docs/source/release-notes/workarea-3-2-29.html.md +0 -126
  486. data/docs/source/release-notes/workarea-3-2-30.html.md +0 -112
  487. data/docs/source/release-notes/workarea-3-2-31.html.md +0 -105
  488. data/docs/source/release-notes/workarea-3-2-32.html.md +0 -56
  489. data/docs/source/release-notes/workarea-3-2-33.html.md +0 -82
  490. data/docs/source/release-notes/workarea-3-2-34.html.md +0 -153
  491. data/docs/source/release-notes/workarea-3-2-35.html.md +0 -91
  492. data/docs/source/release-notes/workarea-3-2-36.html.md +0 -118
  493. data/docs/source/release-notes/workarea-3-2-37.html.md +0 -46
  494. data/docs/source/release-notes/workarea-3-2-38.html.md +0 -23
  495. data/docs/source/release-notes/workarea-3-2-39.html.md +0 -42
  496. data/docs/source/release-notes/workarea-3-2-4.html.md +0 -109
  497. data/docs/source/release-notes/workarea-3-2-40.html.md +0 -25
  498. data/docs/source/release-notes/workarea-3-2-41.html.md +0 -90
  499. data/docs/source/release-notes/workarea-3-2-5.html.md +0 -186
  500. data/docs/source/release-notes/workarea-3-2-6.html.md +0 -173
  501. data/docs/source/release-notes/workarea-3-2-7.html.md +0 -89
  502. data/docs/source/release-notes/workarea-3-2-8.html.md +0 -137
  503. data/docs/source/release-notes/workarea-3-2-9.html.md +0 -219
  504. data/docs/source/release-notes/workarea-3-3-0.html.md +0 -1272
  505. data/docs/source/release-notes/workarea-3-3-1.html.md +0 -324
  506. data/docs/source/release-notes/workarea-3-3-10.html.md +0 -69
  507. data/docs/source/release-notes/workarea-3-3-11.html.md +0 -72
  508. data/docs/source/release-notes/workarea-3-3-12.html.md +0 -136
  509. data/docs/source/release-notes/workarea-3-3-13.html.md +0 -61
  510. data/docs/source/release-notes/workarea-3-3-14.html.md +0 -196
  511. data/docs/source/release-notes/workarea-3-3-15.html.md +0 -167
  512. data/docs/source/release-notes/workarea-3-3-16.html.md +0 -234
  513. data/docs/source/release-notes/workarea-3-3-17.html.md +0 -82
  514. data/docs/source/release-notes/workarea-3-3-18.html.md +0 -165
  515. data/docs/source/release-notes/workarea-3-3-19.html.md +0 -106
  516. data/docs/source/release-notes/workarea-3-3-2.html.md +0 -72
  517. data/docs/source/release-notes/workarea-3-3-20.html.md +0 -116
  518. data/docs/source/release-notes/workarea-3-3-21.html.md +0 -228
  519. data/docs/source/release-notes/workarea-3-3-22.html.md +0 -125
  520. data/docs/source/release-notes/workarea-3-3-23.html.md +0 -154
  521. data/docs/source/release-notes/workarea-3-3-24.html.md +0 -70
  522. data/docs/source/release-notes/workarea-3-3-25.html.md +0 -114
  523. data/docs/source/release-notes/workarea-3-3-26.html.md +0 -260
  524. data/docs/source/release-notes/workarea-3-3-27.html.md +0 -138
  525. data/docs/source/release-notes/workarea-3-3-28.html.md +0 -147
  526. data/docs/source/release-notes/workarea-3-3-29.html.md +0 -63
  527. data/docs/source/release-notes/workarea-3-3-3.html.md +0 -153
  528. data/docs/source/release-notes/workarea-3-3-30.html.md +0 -102
  529. data/docs/source/release-notes/workarea-3-3-31.html.md +0 -57
  530. data/docs/source/release-notes/workarea-3-3-32.html.md +0 -44
  531. data/docs/source/release-notes/workarea-3-3-33.html.md +0 -114
  532. data/docs/source/release-notes/workarea-3-3-34.html.md +0 -29
  533. data/docs/source/release-notes/workarea-3-3-4.html.md +0 -332
  534. data/docs/source/release-notes/workarea-3-3-5.html.md +0 -242
  535. data/docs/source/release-notes/workarea-3-3-6.html.md +0 -100
  536. data/docs/source/release-notes/workarea-3-3-7.html.md +0 -148
  537. data/docs/source/release-notes/workarea-3-3-8.html.md +0 -163
  538. data/docs/source/release-notes/workarea-3-3-9.html.md +0 -93
  539. data/docs/source/release-notes/workarea-3-4-0.html.md +0 -580
  540. data/docs/source/release-notes/workarea-3-4-1.html.md +0 -150
  541. data/docs/source/release-notes/workarea-3-4-10.html.md +0 -72
  542. data/docs/source/release-notes/workarea-3-4-11.html.md +0 -60
  543. data/docs/source/release-notes/workarea-3-4-12.html.md +0 -155
  544. data/docs/source/release-notes/workarea-3-4-15.html.md +0 -100
  545. data/docs/source/release-notes/workarea-3-4-16.html.md +0 -88
  546. data/docs/source/release-notes/workarea-3-4-2.html.md +0 -188
  547. data/docs/source/release-notes/workarea-3-4-3.html.md +0 -136
  548. data/docs/source/release-notes/workarea-3-4-4.html.md +0 -114
  549. data/docs/source/release-notes/workarea-3-4-5.html.md +0 -275
  550. data/docs/source/release-notes/workarea-3-4-6.html.md +0 -169
  551. data/docs/source/release-notes/workarea-3-4-7.html.md +0 -162
  552. data/docs/source/release-notes/workarea-3-4-8.html.md +0 -95
  553. data/docs/source/release-notes/workarea-3-4-9.html.md +0 -135
  554. data/docs/source/release-notes.html.md +0 -261
  555. data/docs/source/search.html.erb +0 -34
  556. data/docs/source/shared/_header.erb +0 -61
  557. data/docs/source/shared/_svgs.erb +0 -17
  558. data/docs/source/style_guide/index.html.erb +0 -382
  559. data/docs/source/stylesheets/_base.scss +0 -125
  560. data/docs/source/stylesheets/_components.scss +0 -669
  561. data/docs/source/stylesheets/_helpers.scss +0 -10
  562. data/docs/source/stylesheets/_opinions.scss +0 -42
  563. data/docs/source/stylesheets/_settings.scss +0 -56
  564. data/docs/source/stylesheets/_typography.scss +0 -119
  565. data/docs/source/stylesheets/site.css.scss +0 -14
  566. data/docs/source/stylesheets/vendor/_avalanche.scss +0 -328
  567. data/docs/source/stylesheets/vendor/_normalize.scss +0 -341
  568. data/docs/source/stylesheets/vendor/highlight/_tomorrow_night_blue.scss +0 -75
  569. data/docs/source/upgrade-guides/workarea-3-4-0.html.md +0 -152
  570. data/docs/source/upgrade-guides.html.md +0 -18
  571. data/docs/workarea_renderer.rb +0 -8
  572. data/docs/yarn.lock +0 -2522
@@ -1,1270 +0,0 @@
1
- ---
2
- title: Products
3
- excerpt: A Workarea application presents a retailer’s catalog to consumers and promotes the sale of those items. Products are representations of the goods and services the retailer is presenting for sale. This guide further explains “product” as a concept with
4
- ---
5
-
6
- # Products
7
-
8
- A Workarea application presents a retailer’s catalog to consumers and promotes the sale of those items. <dfn>Products</dfn> are representations of the goods and services the retailer is presenting for sale. This guide further explains “product” as a concept within the Workarea platform.
9
-
10
- A retailer’s catalog is modeled within the Workarea `Catalog` as products and variants (which each have details) and catalog product images. Additional records exist outside the `Catalog` module to represent the inventory, pricing, and shipping details for each item.
11
-
12
- Presenting a product requires wrapping the catalog product document in an appropriate view model, which creates a view of the product suitable for either consumers shopping in the Storefront or administrators managing the catalog in the Admin.
13
-
14
- Admins manage products, variants, and product images through the Admin web interface and data files. Developers have additional access to command line and programmatic interfaces. Regardless of interface, product management is affected by various application and document states.
15
-
16
- Admins also manage the placement of products within the Storefront, optimizing what products consumers see while browsing. The systems that facilitate these optimizations rely on additional product representations of which developers should be aware. Additionally, each presented product is affected by various browsing states.
17
-
18
- After narrowing to specific products, consumers view the details of each product, which presents options the consumer can use to reduce the product to a specific item. The display of the options and other product data are determined by the product template and several states related to showing a product.
19
-
20
- ## Modeling the Retailer’s Catalog
21
-
22
- Each retailer maintains a <dfn>catalog</dfn>, a list of items for sale. These items are often _goods_ with physical inventory, but may also include intangible items such as digital downloads and warranties, and _services_, such as units of repair time or tech support. Regardless of type, the retailer maintains records for each item, such as its description and details, pricing, inventory, location within a warehouse, and shipping weight and dimensions. These records are often managed across many systems, such as point of sale, inventory, accounting, warehouse/fulfillment, and mail order catalog. To manage each item across systems, the retailer identifies each item with a <dfn>SKU</dfn>: an id internal to the retailer and unique across all the retailer’s systems.
23
-
24
- The Workarea platform is similarly divided into multiple subsystems, many of which keep their own records for the retailer’s merchandise. These records are related by SKU, allowing multiple representations of the same item to be joined when needed.
25
-
26
- ### Catalog Products & Variants
27
-
28
- Within the `Workarea::Catalog` namespace are `Product` and `Variant` [application documents](application-document.html). A <dfn>catalog product</dfn> represents a group of related but varying items for sale. Each catalog product embeds a collection of <dfn>variants</dfn>, each of which represents a distinct item for sale within that product.
29
-
30
- Catalogs are generally organized in this fashion: with groups of products sharing some information (such as a name and description) while varying on other details (such as color and size).&nbsp;<sup><a id="note-1-context" href="#notes">[1]</a></sup>
31
-
32
- Grouping items facilitates the usual shopping flow: first reduce the catalog to a product of interest (such as a cotton t-shirt), and then further reduce that product to a particular item to be purchased (for example, the _large_, _blue_ cotton t-shirt). The first part of this flow is known as _browsing_, where consumers shop _by product_. The second part is known as _showing_ or _product detail page_, where consumers see _options_, which allow easy comparison of a specific product’s variants.&nbsp;<sup><a id="note-2-context" href="#notes">[2]</a></sup> Grouping into products also benefits the retailer, allowing them to share data across items, attach discounts to groups of similar items, and view analytics by these groupings.
33
-
34
- A product names and describes a group of items and stores the data that all the items in the group share. The only required field is `name`. Print a product as a document to get an overview of the catalog product interface.
35
-
36
- ```ruby
37
- pp Workarea::Catalog::Product.find_by(name: 'Tropical Drink Mix').as_document
38
- # {"_id"=>"5A74109BFA",
39
- # "tags"=>[],
40
- # "active"=>{"en"=>true},
41
- # "subscribed_user_ids"=>[],
42
- # "details"=>{"en"=>{"Ingredients"=>["Pure Cane Sugar", "Natural Flavor"]}},
43
- # "filters"=>{"en"=>{}},
44
- # "template"=>"generic",
45
- # "purchasable"=>true,
46
- # "name"=>{"en"=>"Tropical Drink Mix"},
47
- # "digital"=>false,
48
- # "slug"=>"tropical-drink-mix",
49
- # "updated_at"=>2018-05-31 15:15:28 UTC,
50
- # "created_at"=>2018-05-31 15:15:28 UTC,
51
- # "variants"=>
52
- # [{"_id"=>BSON::ObjectId('5b101190eefbfe0cb1018da8'),
53
- # "active"=>{"en"=>true},
54
- # "details"=>{"en"=>{}},
55
- # "sku"=>"mango-hurricane-mix",
56
- # "name"=>{"en"=>"Mango Hurricane"},
57
- # "position"=>0},
58
- # {"_id"=>BSON::ObjectId('5b101190eefbfe0cb1018da9'),
59
- # "active"=>{"en"=>true},
60
- # "details"=>{"en"=>{}},
61
- # "sku"=>"coconut-cyclone-mix",
62
- # "name"=>{"en"=>"Coconut Cyclone"},
63
- # "position"=>1},
64
- # {"_id"=>BSON::ObjectId('5b101190eefbfe0cb1018daa'),
65
- # "active"=>{"en"=>true},
66
- # "details"=>{"en"=>{}},
67
- # "sku"=>"pineapple-typhoon-mix",
68
- # "name"=>{"en"=>"Pineapple Typhoon"},
69
- # "position"=>2}],
70
- # "last_indexed_at"=>2018-05-31 15:15:28 UTC}
71
- ```
72
-
73
- Notice above that several of the fields are internationalized; their values are keyed by locale.
74
-
75
- Also observe the embedded collection of variants. Each variant represents a distinct variation of the product, giving it a name/id (through the `id`, `sku`, and `name` fields), description (through details), and an administrable position relative to its siblings.
76
-
77
- You must provide the `sku` value when creating a variant, since this is a retailer-supplied ID that Workarea cannot generate. The variant’s SKU relates the variant to other models representing the same item within Workarea, and to other representations of the same item across other systems managed by the retailer.
78
-
79
- Note that product and variant implement some of the same interface. One example of this is `active`, which both models inherit from `Workarea::Releasable`. Another example is the details interface, covered next.
80
-
81
- ### Details
82
-
83
- Product and variant both inherit from `Workarea::Details` and therefore implement the same <dfn>details</dfn> interface. Details are administrable attributes of a product and its variants, which are displayed to consumers within the Storefront.
84
-
85
- A product and each of its variants stores a `details` hash, where the keys are typically strings and the values are collections of non-blank, scalar values (again, often strings). These are flexible data structures that serve platform-defined and application-defined purposes.
86
-
87
- The items that make up a product share some details and vary on others. Store the shared details on the product. Store on each variant the details that distinguish that variant from its siblings. Many examples of this follow.
88
-
89
- Note that a variant’s SKU effectively encodes its details, by providing an ID which maps to a particular “configuration” of the product. This encoding may be observable in the ID itself. For example, the SKU _TSHIRT-BLACK-SMALL_ clearly identifies a particular product (_T-Shirt_) and particular variant details (a color, _black_, and a size, _small_).
90
-
91
- Details on the _product_ are used for search text and implementation-specific use cases (perhaps a product template which enumerates the details when showing the product). Details on the _variant_ are used to create the product options which are presented to the consumer when showing the product.&nbsp;<sup><a id="note-3-context" href="#notes">[3]</a></sup>
92
-
93
- The following examples demonstrate the process of mapping catalog data to products and variants. Each example provides a possible solution and some commentary.
94
-
95
- The first example is presented in Table 1 and Listing 1.
96
-
97
- <caption>
98
- <p>Table 1</p>
99
- <p>A subset of catalog data for keyed padlocks.</p>
100
- </caption>
101
-
102
- | SKU | Weather Resistance | Shackle Locking | Shackle Material | Shackle Length | Shackle Diameter |
103
- | --- | --- | --- | --- | --- | --- |
104
- | KEYPAD-S-1-14 | Covered | Dual ball bearing | Steel | 1" | 1/4" |
105
- | KEYPAD-S-1-12 | Covered | Dual ball bearing | Steel | 1" | 1/2" |
106
- | KEYPAD-S-2-14 | Covered | Dual ball bearing | Steel | 2" | 1/4" |
107
- | KEYPAD-S-2-12 | Covered | Dual ball bearing | Steel | 2" | 1/2" |
108
- | KEYPAD-B-1-14 | Covered | Dual ball bearing | Brass | 1" | 1/4" |
109
- | KEYPAD-B-1-12 | Covered | Dual ball bearing | Brass | 1" | 1/2" |
110
- | KEYPAD-B-2-14 | Covered | Dual ball bearing | Brass | 2" | 1/4" |
111
- | KEYPAD-B-2-12 | Covered | Dual ball bearing | Brass | 2" | 1/2" |
112
-
113
- <!-- <figure id="listing-1">
114
- <figcaption>
115
- <p>Listing 1</p>
116
- <p>Creating a “Keyed Padlock” product (with variants) in Workarea from the data in <a href="#table-1">Table 1</a>. This represents one possible solution.</p>
117
- </figcaption> -->
118
-
119
- Listing 1
120
- Creating a “Keyed Padlock” product (with variants) in Workarea from the data in <a href="#table-1">Table 1</a>. This represents one possible solution.
121
-
122
- ```ruby
123
- name: 'Keyed Padlock',
124
- details: {
125
- 'Weather Resistance' => ['Covered'],
126
- 'Shackle Locking' => ['Dual ball bearing']
127
- },
128
- variants: [
129
- {
130
- sku: 'KEYPAD-S-1-14',
131
- details: {
132
- 'Shackle Material' => ['Steel'],
133
- 'Shackle Length' => ['1"'],
134
- 'Shackle Diameter' => ['1/4"']
135
- }
136
- },
137
- {
138
- sku: 'KEYPAD-S-1-12',
139
- details: {
140
- 'Shackle Material' => ['Steel'],
141
- 'Shackle Length' => ['1"'],
142
- 'Shackle Diameter' => ['1/2"']
143
- }
144
- },
145
- {
146
- sku: 'KEYPAD-S-2-14',
147
- details: {
148
- 'Shackle Material' => ['Steel'],
149
- 'Shackle Length' => ['2"'],
150
- 'Shackle Diameter' => ['1/4"']
151
- }
152
- },
153
- {
154
- sku: 'KEYPAD-S-2-12',
155
- details: {
156
- 'Shackle Material' => ['Steel'],
157
- 'Shackle Length' => ['2"'],
158
- 'Shackle Diameter' => ['1/2"']
159
- }
160
- },
161
- {
162
- sku: 'KEYPAD-B-1-14',
163
- details: {
164
- 'Shackle Material' => ['Brass'],
165
- 'Shackle Length' => ['1"'],
166
- 'Shackle Diameter' => ['1/4"']
167
-
168
- }
169
-
170
- },
171
- {
172
- sku: 'KEYPAD-B-1-12',
173
- details: {
174
- 'Shackle Material' => ['Brass'],
175
- 'Shackle Length' => ['1"'],
176
- 'Shackle Diameter' => ['1/2"']
177
-
178
- }
179
-
180
- },
181
- {
182
- sku: 'KEYPAD-B-2-14',
183
- details: {
184
- 'Shackle Material' => ['Brass'],
185
- 'Shackle Length' => ['2"'],
186
- 'Shackle Diameter' => ['1/4"']
187
- }
188
- },
189
- {
190
- sku: 'KEYPAD-B-2-12',
191
- details: {
192
- 'Shackle Material' => ['Brass'],
193
- 'Shackle Length' => ['2"'],
194
- 'Shackle Diameter' => ['1/2"']
195
- }
196
- }
197
- ]
198
- )
199
- ```
200
- <!-- </figure> -->
201
-
202
- Note the following about the example presented in Table 1 and Listing 1:
203
-
204
- - The values for _Weather Resistance_ and _Shackle Locking_ are consistent across all items and are therefore stored on the product.
205
- - The items vary by _Shackle Material_, _Shackle Length_, and _Shackle Diameter_, so those details are stored on the variants.
206
- - The data uses English language and measurements. Since the `details` field is internationalized. You could store different values (such as metric units) using a different locale.
207
-
208
- Table 2 and Listing 2 provide another example.
209
-
210
- <caption>
211
- <p>Table 2</p>
212
- <p>A subset of catalog data for fitted baseball caps.</p>
213
- </caption>
214
-
215
- | SKU | Fitting Type | Materials | Color | Size |
216
- | --- | --- | --- | --- | --- |
217
- | BALLCAP-BLACK-S | Elastic | Cotton/Polyester | Black/White | Small |
218
- | BALLCAP-BLACK-M | Elastic | Cotton/Polyester | Black/White | Medium |
219
- | BALLCAP-BLACK-L | Elastic | Cotton/Polyester | Black/White | Large |
220
- | BALLCAP-BLUE-S | Elastic | Cotton/Polyester | Blue/White | Small |
221
- | BALLCAP-BLUE-M | Elastic | Cotton/Polyester | Blue/White | Medium |
222
- | BALLCAP-BLUE-L | Elastic | Cotton/Polyester | Blue/White | Large |
223
- | BALLCAP-RWB-S | Elastic | Cotton/Polyester | Red/White/Blue | Small |
224
- | BALLCAP-RWB-M | Elastic | Cotton/Polyester | Red/White/Blue | Medium |
225
- | BALLCAP-RWB-L | Elastic | Cotton/Polyester | Red/White/Blue | Large |
226
-
227
- <!-- <figure id="listing-2">
228
- <figcaption>
229
- <p>Listing 2</p>
230
- <p>Creating a “Fitted Baseball Cap” product (with variants) in Workarea from the data in <a href="#table-2">Table 2</a>. This represents one possible solution.</p>
231
- </figcaption> -->
232
-
233
- Listing 2
234
- Creating a “Fitted Baseball Cap” product (with variants) in Workarea from the data in <a href="#table-2">Table 2</a>. This represents one possible solution.
235
-
236
- ```ruby
237
- Workarea::Catalog::Product.create(
238
- name: 'Fitted Baseball Cap',
239
- details: {
240
- 'Fitting Type' => ['Elastic'],
241
- 'Materials' => ['Cotton', 'Polyester']
242
- },
243
- variants: [
244
- {
245
- sku: 'BALLCAP-BLACK-S',
246
- details: {
247
- 'Color' => ['Black/White'],
248
- 'Size' => ['Small']
249
- }
250
- },
251
- {
252
- sku: 'BALLCAP-BLACK-M',
253
- details: {
254
- 'Color' => ['Black/White'],
255
- 'Size' => ['Medium']
256
- }
257
- },
258
- {
259
- sku: 'BALLCAP-BLACK-L',
260
- details: {
261
- 'Color' => ['Black/White'],
262
- 'Size' => ['Large']
263
- }
264
- },
265
- {
266
- sku: 'BALLCAP-BLUE-S',
267
- details: {
268
- 'Color' => ['Blue/White'],
269
- 'Size' => ['Small']
270
- }
271
- },
272
- {
273
- sku: 'BALLCAP-BLUE-M',
274
- details: {
275
- 'Color' => ['Blue/White'],
276
- 'Size' => ['Medium']
277
- }
278
- },
279
- {
280
- sku: 'BALLCAP-BLUE-L',
281
- details: {
282
- 'Color' => ['Blue/White'],
283
- 'Size' => ['Large']
284
- }
285
- },
286
- {
287
- sku: 'BALLCAP-RWB-S',
288
- details: {
289
- 'Color' => ['Red/White/Blue'],
290
- 'Size' => ['Small']
291
- }
292
- },
293
- {
294
- sku: 'BALLCAP-RWB-M',
295
- details: {
296
- 'Color' => ['Red/White/Blue'],
297
- 'Size' => ['Medium']
298
- }
299
- },
300
- {
301
- sku: 'BALLCAP-RWB-L',
302
- details: {
303
- 'Color' => ['Red/White/Blue'],
304
- 'Size' => ['Large']
305
- }
306
- }
307
- ]
308
- )
309
- ```
310
- <!-- </figure> -->
311
-
312
- Note the following regarding the example presented in Table 2 and Listing 2:
313
-
314
- - _Materials_ are stored (on the product) as multiple values so they can be enumerated for display or other purposes.
315
- - _Color_ is stored (on each variant) as a single value because the retailer would like to present each combined color value to consumers as a single product option. This retailer is using <cite>Workarea Swatches</cite> to represent each combined color with a multi-color image.&nbsp;<sup><a id="note-4-context" href="#notes">[4]</a></sup>
316
-
317
- Now see Table 3 and Listing 3 for a third example.
318
-
319
- <caption>
320
- <p>Table 3</p>
321
- <p>A subset of catalog data for extended service plans (warranties).</p>
322
- </caption>
323
-
324
- | SKU | Duration |
325
- | --- | --- |
326
- | B45678 | 3 years |
327
- | A57893 | 5 years |
328
-
329
- <!--
330
- <figure id="listing-3">
331
- <figcaption>
332
- <p>Listing 3</p>
333
- <p>Creating an “Extended Service Plan” product (with variants) in Workarea from the data in <a href="#table-3">Table 3</a>. This represents one possible solution.</p>
334
- </figcaption>
335
- -->
336
-
337
- Listing 3
338
- Creating an “Extended Service Plan” product (with variants) in Workarea from the data in <a href="#table-3">Table 3</a>. This represents one possible solution.
339
-
340
- ```ruby
341
- Workarea::Catalog::Product.create(
342
- name: 'Extended Service Plan',
343
- variants: [
344
- {
345
- sku: 'B45678',
346
- details: {
347
- 'Duration' => ['3 years']
348
- }
349
- },
350
- {
351
- sku: 'A57893',
352
- details: {
353
- 'Duration' => ['5 years']
354
- }
355
- }
356
- ]
357
- )
358
- ```
359
- <!-- </figure> -->
360
-
361
- Notice in the 3rd example the SKUs aren’t as user-friendly as they were in the previous examples. However, SKUs are assigned by the retailer and should not be modified. Despite their cryptic appearance, they effectively encode the details of the variant by providing a unique ID that all relevant parties (retailer, Workarea, fulfillment system, etc) can decode.
362
-
363
- Also note the details in the 3rd example have only one value. In such a case, the retailer may prefer to assign a name to the variant and forgo the use of variant details. See Table 4 and Listing 4 for an example that fits this description.
364
-
365
- <caption>
366
- <p>Table 4</p>
367
- <p>A subset of catalog data for tropical drink mixes.</p>
368
- </caption>
369
-
370
- | SKU | Ingredients |
371
- | --- | --- |
372
- | mango-hurricane-mix | Pure Cane Sugar, Natural Flavor |
373
- | coconut-cyclone-mix | Pure Cane Sugar, Natural Flavor |
374
- | pineapple-typhoon-mix | Pure Cane Sugar, Natural Flavor |
375
-
376
- <!--
377
- <figure id="listing-4">
378
- <figcaption>
379
- <p>Listing 4</p>
380
- <p>Creating a “Tropical Drink Mix” product (with variants) in Workarea from the data in <a href="#table-4">Table 4</a>. This represents one possible solution.</p>
381
- </figcaption>
382
- -->
383
-
384
- Listing 4
385
- Creating a “Tropical Drink Mix” product (with variants) in Workarea from the data in <a href="#table-4">Table 4</a>. This represents one possible solution.
386
-
387
- ```ruby
388
- Workarea::Catalog::Product.create(
389
- name: 'Tropical Drink Mix',
390
- details: {
391
- 'Ingredients' => ['Pure Cane Sugar', 'Natural Flavor']
392
- },
393
- variants: [
394
- {
395
- sku: 'mango-hurricane-mix',
396
- name: 'Mango Hurricane'
397
- },
398
- {
399
- sku: 'coconut-cyclone-mix',
400
- name: 'Coconut Cyclone'
401
- },
402
- {
403
- sku: 'pineapple-typhoon-mix',
404
- name: 'Pineapple Typhoon'
405
- }
406
- ]
407
- )
408
- ```
409
- <!-- </figure> -->
410
-
411
- As mentioned above, this final example assigns a name to each variant. These names may display to the consumer when showing the product.
412
-
413
- Review all the examples above and observe how some of them store details on _only the product_, _only the variants_, or _both the product and the variants_. Remember! A product and its embedded variants each store their own details hash, so consider which object to write to or query from when operating on details.
414
-
415
- ```ruby
416
- catalog_product =
417
- Workarea::Catalog::Product.find_by(name: 'Fitted Baseball Cap')
418
-
419
- catalog_product.details
420
- # => {"Fitting Type"=>["Elastic"], "Materials"=>["Cotton", "Polyester"]}
421
-
422
- catalog_product.variants.first.details
423
- # => {"Color"=>["Black/White"], "Size"=>["Small"]}
424
-
425
- catalog_product.variants.second.details
426
- # => {"Color"=>["Black/White"], "Size"=>["Medium"]}
427
- ```
428
-
429
- Finally, products and variants implement instance methods for fetching and testing details.
430
-
431
- ```ruby
432
- puts Workarea::Details.instance_methods(false).sort
433
- # fetch_detail
434
- # has_detail?
435
- # matches_detail?
436
- # matches_details?
437
- # update_details
438
- ```
439
-
440
- ### Catalog Product Images
441
-
442
- In addition to variants, each catalog product embeds a collection of product images. Each product image is a document of type `Catalog::ProductImage` and has an attachment (an image file). Product images are [Dragonfly models](http://markevans.github.io/dragonfly/models) and implement that interface. A product image also has a `position` field for administrating display order, and an `option` field to associate the image with a product option.
443
-
444
- The following examples use the “Extended Service Plan” product created in Listing 3 for demonstration. This product represents intangible goods that have no product photography, however, you can still use generated images to improve the shopping experience.
445
-
446
- First, generate some image files. Admittedly, these images are not pretty, but they demonstrate the concepts sufficiently.
447
-
448
- ```bash
449
- $ convert \
450
- > -background lightblue \
451
- > -fill blue \
452
- > -font Helvetica \
453
- > -size 400x600 \
454
- > -pointsize 72 \
455
- > -gravity center \
456
- > 'label:3 Years' \
457
- > 3_years.jpg
458
-
459
- $ convert \
460
- > -background blue \
461
- > -fill lightblue \
462
- > -font Helvetica \
463
- > -size 400x600 \
464
- > -pointsize 72 \
465
- > -gravity center \
466
- > 'label:5 Years' \
467
- > 5_years.jpg
468
- $
469
- ```
470
-
471
- Next, create some product images within the product from those files, and explore the product image interface.
472
-
473
- ```ruby
474
- catalog_product =
475
- Workarea::Catalog::Product.find_by(name: 'Extended Service Plan')
476
-
477
- catalog_product.images.create(
478
- image: File.new('3_years.jpg'),
479
- option: '3_years'
480
- )
481
- catalog_product.images.create(
482
- image: File.new('5_years.jpg'),
483
- option: '5_years'
484
- )
485
-
486
- catalog_product.images.count
487
- # => 2
488
-
489
- product_image = catalog_product.images.first
490
-
491
- product_image.class
492
- # => Workarea::Catalog::ProductImage
493
-
494
- product_image.name
495
- # => "3_years.jpg"
496
-
497
- product_image.option
498
- # => "3_years"
499
-
500
- product_image.position
501
- # => 0
502
-
503
- product_image.format
504
- # => "jpeg"
505
-
506
- product_image.width
507
- # => 400
508
-
509
- product_image.height
510
- # => 600
511
- ```
512
-
513
- Product images are neither releasable nor are any of their fields internationalized. Therefore, application state does not affect product images.
514
-
515
- Notably, product images are stored on the _product_, not the variants. You can associate each image with a product option. Administration of the `position` and `option` fields therefore affects the presentation of a product (also see Primary Image).&nbsp;<sup><a id="note-5-context" href="#notes">[5]</a></sup>
516
-
517
- Finally, there is also a `Catalog::ProductPlaceholderImage`, which is used when presenting a product that has no embedded images. A product placeholder image implements the same interface as a product image, but there is only a single instance of the product placeholder image, accessible as `Catalog::ProductPlaceholderImage.cached`.&nbsp;<sup><a id="note-6-context" href="#notes">[6]</a></sup>
518
-
519
- ### Inventory, Pricing & Shipping SKUs
520
-
521
- Beyond the Workarea `Catalog` module, several other Workarea subsystems store records representing the items of the retailer’s catalog. These additional models are outside the scope of this guide, however, the following examples briefly demonstrate the relationships of these models.
522
-
523
- - `Workarea::Inventory` stores an `Inventory::Sku` for each item
524
- - `Workarea::Pricing` stores a `Pricing::Sku` for each item
525
- - `Workarea::Shipping` stores a `Shipping::Sku` for each item
526
- - These models are related to each other and to the models of the `Catalog` by the retailer-provided SKU
527
-
528
- For example: given a SKU, find the pricing, inventory, shipping, and product that match the SKU:
529
-
530
- ```ruby
531
- sku = 'BALLCAP-BLUE-M'
532
- pricing_sku = Workarea::Pricing::Sku.find(sku)
533
- inventory_sku = Workarea::Inventory::Sku.find(sku)
534
- shipping_sku = Workarea::Shipping::Sku.find(sku)
535
- catalog_product = Workarea::Catalog::Product.find_by_sku(sku)
536
- ```
537
-
538
- Notice the different method used to query for the product. This is because the SKU values are stored on the embedded variants, not the product itself.
539
-
540
- As another example: given a catalog product ID, find the variants, SKUs, inventory collection, pricing collection, and shipping SKUs that correlate with the product:
541
-
542
- ```ruby
543
- catalog_product_id = 'ABC123'
544
- catalog_product = Workarea::Product.find(catalog_product_id)
545
- variants = catalog_product.variants
546
- skus = catalog_product.skus
547
- inventory_collection = Workarea::Inventory::Collection.new(skus)
548
- pricing_collection = Workarea::Pricing::Collection.new(skus)
549
- shipping_skus = Workarea::Shipping::Sku.in(id: skus).to_a
550
- ```
551
-
552
- There are also some additional models that represent products for use within the search, recommendations, and analytics subsystems, which are related by product ID. These will be explored further in an update to this guide.
553
-
554
- ## Presenting a Product
555
-
556
- Workarea Storefront presents the retailer’s catalog to consumers using _products_ and does so in a variety of places:
557
-
558
- - On dedicated product pages (product detail/show pages)
559
- - Within search results and categories (product browse pages)
560
- - As recommendations
561
- - Within content
562
-
563
- <figure id="figure-1">
564
- <figcaption>
565
- <p>Figure 1</p>
566
- <p>A product detail page (show page) in the Storefront</p>
567
- </figcaption>
568
- <p><%= image_tag "images/storefront-product-show-page.png", alt: "Storefront product show page" %></p>
569
- </figure>
570
-
571
- <figure id="figure-2">
572
- <figcaption>
573
- <p>Figure 2</p>
574
- <p>A category page (browse page) in the Storefront</p>
575
- </figcaption>
576
- <p><%= image_tag "images/storefront-product-browse-page.png", alt: "Storefront product browse page" %></p>
577
- </figure>
578
-
579
- Underlying each of the presented products is a `Catalog::Product` document.
580
-
581
- Admin users with catalog access can additionally view the same catalog product through the Admin. In fact, like the Storefront, the Admin presents products in a variety of places:
582
-
583
- - On dedicated product management pages
584
- - Within search results and index pages
585
- - Within dashboards
586
- - Within the “featured products” UI
587
-
588
- <figure id="figure-3">
589
- <figcaption>
590
- <p>Figure 3</p>
591
- <p>A product show page in the Admin</p>
592
- </figcaption>
593
- <p><%= image_tag "images/admin-product-show-page.png", alt: "Admin product show page" %></p>
594
- </figure>
595
-
596
- <figure id="figure-4">
597
- <figcaption>
598
- <p>Figure 4</p>
599
- <p>A products index page in the Admin</p>
600
- </figcaption>
601
- <p><%= image_tag "images/admin-products-index-page.png", alt: "Admin products index page" %></p>
602
- </figure>
603
-
604
- And like the Storefront, underlying each displayed product is a catalog product document.
605
-
606
- However, in figures 1, 2, 3, and 4, you can see the presentations of the products include data from outside the catalog product document. To display a product, a controller wraps a catalog product document in an appropriate [view model](view-models.html) which is responsible for presenting the document within a particular context (e.g.&nbsp;Storefront or Admin). The view model extends the model with additional presentation logic, and joins the model with the other models needed to create the representation of the product the user within that context is expecting to see.
607
-
608
- To demonstrate, consider the differing views of a product for consumers and administrators.
609
-
610
- ### Consumers’ View of the Catalog Product
611
-
612
- Throughout the Storefront, each catalog product is wrapped in an instance of `Storefront::ProductViewModel` for presentation.&nbsp;<sup><a id="note-7-context" href="#notes">[7]</a></sup> The Storefront product view model is responsible for creating the view of the product a consumer is expecting to see in the Storefront while shopping. This view includes details beyond the catalog product, such as inventory, pricing, navigation, and recommendations (see Figure 1). The view model extends the existing interface of the catalog product and augments the interface with additional presentation logic and additional data joined from other models.
613
-
614
- <!-- <figure id="listing-5">
615
- <figcaption>
616
- <p>Listing 5</p>
617
- <p>The Storefront view model extends the catalog product interface</p>
618
- </figcaption>
619
- -->
620
-
621
- Listing 5
622
- The Storefront view model extends the catalog product interface
623
-
624
- ```ruby
625
- changes_to_the_product_interface =
626
- Workarea::Storefront::ProductViewModel.instance_methods(false) &amp;
627
- Workarea::Catalog::Product.instance_methods
628
-
629
- puts changes_to_the_product_interface.sort
630
- # browser_title
631
- # cache_key
632
- # images
633
- # meta_description
634
- # purchasable?
635
- # variants
636
-
637
- additions_to_the_product_interface =
638
- Workarea::Storefront::ProductViewModel.instance_methods(false) -
639
- Workarea::Catalog::Product.instance_methods
640
-
641
- puts additions_to_the_product_interface.sort
642
- # breadcrumbs
643
- # browse_link_options
644
- # catalog_id
645
- # current_sku
646
- # current_variant
647
- # default_category
648
- # has_prices?
649
- # inventory
650
- # inventory_purchasable?
651
- # inventory_status
652
- # on_sale?
653
- # one_price?
654
- # original_max_price
655
- # original_min_price
656
- # pricing
657
- # primary_image
658
- # recommendations
659
- # sell_max_price
660
- # sell_min_price
661
- # show_original_range?
662
- # show_sell_range?
663
- # sku_options</code></pre>
664
- ```
665
- <!-- </figure> -->
666
-
667
- Listing 5 demonstrates how the product interface is modified when presenting a product in the Storefront, such as:
668
-
669
- - `purchasable?` is redefined to consider pricing and inventory
670
- - `variants` is modified to include only those variants that are active and have displayable inventory
671
- - `browser_title` and `meta_description` are changed to fall back to `name` and `description` when blank
672
- - `primary_image` encapsulates the logic for determining which image should represent the product when displaying it
673
- - `breadcrumbs` join the catalog product with its position within the navigation taxonomy
674
- - `recommendations` join the catalog product with its recommendations
675
- - Various methods related to inventory and pricing join the catalog product with those subsystems
676
-
677
- In all cases, the changes to the interface reflect the context of a consumer shopping the Storefront and present a product which aligns with the consumer’s expectations of the “product” concept.
678
-
679
- ### Administrators’ View of the Catalog Product
680
-
681
- Throughout the Admin, each catalog product is wrapped in an instance of `Admin::ProductViewModel` for presentation. This view model similarly extends and augments the catalog product interface, but for a different context: administrators responsible for managing the catalog and store.
682
-
683
- <!-- <figure id="listing-6">
684
- <figcaption>
685
- <p>Listing 6</p>
686
- <p>The Admin view model extends the catalog product interface</p>
687
- </figcaption> -->
688
-
689
- Listing 6
690
- The Admin view model extends the catalog product interface
691
-
692
- ```ruby
693
- changes_to_the_product_interface =
694
- Workarea::Admin::ProductViewModel.instance_methods(false) &amp;
695
- Workarea::Catalog::Product.instance_methods
696
-
697
- puts changes_to_the_product_interface.sort
698
- # categories
699
-
700
- additions_to_the_product_interface =
701
- Workarea::Admin::ProductViewModel.instance_methods(false) -
702
- Workarea::Catalog::Product.instance_methods
703
-
704
- puts additions_to_the_product_interface.sort
705
- # analytics
706
- # available_inventory
707
- # categorization
708
- # content
709
- # customization_options
710
- # default_category
711
- # displayable?
712
- # featured_categories
713
- # has_prices?
714
- # ignore_inventory?
715
- # images_by_option
716
- # inventory
717
- # on_sale?
718
- # one_price?
719
- # options
720
- # original_max_price
721
- # original_min_price
722
- # pricing
723
- # pricing?
724
- # primary_image
725
- # rules_categories
726
- # sales
727
- # sell_max_price
728
- # sell_min_price
729
- # show_original_range?
730
- # show_sell_range?
731
- # storefront_recommendations
732
- # storefront_view_model
733
- # templates
734
- # timeline
735
- # variant_sell_price</code></pre>
736
- ```
737
- <!-- </figure> -->
738
-
739
- Listing 6 demonstrates the changes to the product interface that make the product suitable for presentation within the Admin. For instance:
740
-
741
- - `analytics` provides analytics data to present insights to the retailer
742
- - `categories` changes to a more sophisticated query that includes the categories that match the product according to product rules, and additional methods related to product categorization are added
743
- - Methods such as `customization_options` and `templates` are used to present menus for product administration
744
- - Remarkably, `storefront_view_model` and `timeline` each return an additional view model wrapping the same catalog product
745
-
746
- In all of these examples, the changes reflect the needs of an administrator rather than a consumer.
747
-
748
- Admins can toggle between these differing views of the same product using links in the Admin toolbar (in the Storefront) and the “View on Storefront” link (in the Admin).
749
-
750
- ## Managing Products, Variants & Product Images
751
-
752
- The Admin view of the product, introduced above, is the primary means for admins to manage catalog products, variants, and product images within Workarea. Workarea 3.3 also introduces data files, allowing admins to import and export data from JSON and CSV files for integration with another system or software application. Developers have additional access to programmatic interfaces with which they can extend the platform, and a command line interface for executing developer-only tasks, such as running seeds.
753
-
754
- ### Admin Web Interface
755
-
756
- Admin users with catalog access can manage products, variants, and product images through the Admin web interface. At a glance, this interface provides the ability to:
757
-
758
- - Search, browse, and show existing products
759
- - From a product show page:
760
- - Edit the product’s fields
761
- - Access the product’s embedded collections:
762
- - Create, edit, delete, and re-order images
763
- - Credit, edit, delete, and re-order variants
764
- - Manage the recommendations settings for the product
765
- - Manage the product’s categorization
766
- - Access a timeline of past and upcoming activity on the product
767
- - Access comments about the product from other admins or write your own comments
768
- - View insights based on Workarea analytics
769
- - Create a new product based on the current product (copy product)
770
- - From the products index page:
771
- - Search, sort, filter, and select to refine results for further action
772
- - Edit each selection sequentially, bulk edit, or bulk delete
773
- - Import or export
774
- - Create a new product
775
-
776
- Refer to figures 3, 4, and 5.
777
-
778
- <figure id="figure-5">
779
- <figcaption>
780
- <p>Figure 5</p>
781
- <p>Editing product fields in the Admin</p>
782
- </figcaption>
783
- <p><%= image_tag "images/editing-product-fields-in-the-admin.png", alt: "Editing product fields in the Admin" %></p>
784
- </figure>
785
-
786
- Since products and variants are releasable, edits may publish immediately or in the future (with a release).
787
-
788
- Creating new products and copying products use multi-step workflows because both actions affect multiple models: the product, its embedded collections (variants and images), and the product’s categorization and navigation.
789
-
790
- Plugins and applications extend this interface, so your application may include additional features not listed above.
791
-
792
- ### Data Files
793
-
794
- Workarea 3.3 introduces importing from and exporting to data files (JSON and CSV). Imports/exports are accessible through the Admin, so administrators can use this feature to integrate Workarea with another software system (for example, importing catalog data exported from a warehouse, inventory, or POS system) or to view/edit Workarea data in another software application (such as a spreadsheet). Improvements to this feature are planned, such as a plugin to allow scheduling of imports and exports. A future guide will cover this feature in detail for developers.
795
-
796
- ### Command Line & Programmatic Interfaces
797
-
798
- Since developers are typically super admins, they can use all the features of the Admin web interface.
799
-
800
- However, they can also complete developer-only tasks related to product management through a command line interface. These tasks require shell access to the particular environment and include:
801
-
802
- - [Seeding](seeds.html#seeding)
803
- - Running repetitive actions with Rails _tasks_
804
- - Running one-off actions non-interactively with Rails _runner_
805
- - Running one-off actions interactively with Rails _console_
806
-
807
- Developers also have access to application and platform source code (through gems and git repositories), allowing platform extensions that facilitate product management. Examples of this are:
808
-
809
- - Extending existing or adding new products [seeds](seeds.html) (See `Workarea::ProductsSeeds`)
810
- - Using existing [test factories](testing.html#factories) within your own [tests](testing.html#writing-new-tests) and [test decorators](testing.html#writing-test-decorators) and extending test factories as needed (See `Workarea::Factories::Catalog`)
811
- - Extending existing or adding new [workers](workers.html) to manage products according to a schedule or in response to events
812
-
813
- Finally, the <cite>Workarea API</cite> plugin provides a JSON over HTTP interface which allows management of products, variants, and product images. This allows for management of these models programmatically over the network. For example, another service can “push” product data to Workarea according to a schedule or events within the other system.
814
-
815
- ### Product State
816
-
817
- Regardless of interface, be aware of application and document states affecting a given product.
818
-
819
- The current Rails environment (and current _site_ if using <cite>Workarea Multi Site</cite>) determine the database to which the MongoDB driver is connected. Therefore the entire catalog products collection will vary on these states.
820
-
821
- Furthermore, the current release and current locale may affect the field values of each product. All field values may vary by release (except for `slug`, which is explicitly not releasable), and the values of internationalized fields may vary by locale.
822
-
823
- It’s also important to understand how administrable fields affect the state of a product when presenting it to consumers in the Storefront. Administration of `active` (products and variants), `purchasable`, `template`, `position` (variants and images), and the administration and availability of inventory and pricing have various effects on products presented in the Storefront (see Product State While Browsing for browsing examples; product showing examples will be included in a future update).
824
-
825
- ## Merchandising & Browsing the Storefront
826
-
827
- Beyond managing the products, administrators need to organize them within the store. Although consumers can navigate to products directly by their slugs (see [Navigable](navigable.html)), this has limited application outside of social media and email marketing. Consumers depend on the store to lead them to the merchandise they are looking for.
828
-
829
- Admins leverage this by managing the shopping experience in a way that entices consumers to buy. This process is called <dfn>merchandising</dfn> and involves a combination of automation (search, recommendations, analytics) and administration (navigation, content, pages, categories, search results customizations, recommendations settings, pricing, discounts). Administrators can manage what products are presented to consumers, along with where, when, and how.
830
-
831
- ### Presenting Results
832
-
833
- As a result of merchandising, consumers experience products in a variety of places in the Storefront, such as:
834
-
835
- - Full page browsing results like categories and search results
836
- - Autocomplete results for quick search as you type navigation
837
- - Content within layouts, navigation menus, content pages, system pages, categories, search results
838
- - Recommendations within layouts, detail pages, carts, emails, and content
839
-
840
- Many of these instances are displaying the products returned as the “results” of one or more API calls to Workarea subsystems, such as analytics, recommendations, and search. API calls of this sort each return an ordered collection of catalog product documents or document IDs (so the documents can be subsequently fetched from MongoDB) for a given query or other criteria. For example, the results could be products:
841
-
842
- - matching a consumer's search query, possibly customized by an administrator
843
- - matching a category, based on product rules and/or featured products
844
- - recommended based on what's in the consumer's cart
845
- - identified as top sellers or trending, based on analytics
846
-
847
- In each case, the products that make up the results are each wrapped in an appropriate product view model and presented to the consumer, as described above in Presenting a Product.
848
-
849
- Similar processes present products to administrators in the Admin within a variety of browsing contexts (search results, jump-to menu, index pages, dashboards).
850
-
851
- ### Additional Product Representations
852
-
853
- To produce the product results described above, some Workarea subsystems maintain their own representations of each catalog product. These additional models and their uses are not covered here in detail but are introduced to provide a complete picture of the “product” concept. Just as each item of the retailer's catalog is modeled across subsystems, so is each catalog product.
854
-
855
- #### Analytics Products
856
-
857
- Workarea's analytics module stores an <dfn>analytics product</dfn> (see `Analytics::Product`) in MongoDB for each catalog product. Analytics products collectively provide the necessary data for product scores and aggregations, such as top sellers, most popular, and average selling price.
858
-
859
- #### Recommendations Settings
860
-
861
- The Workarea recommendations subsystem stores <dfn>recommendations settings</dfn> (see `Recommendations::Settings`) in MongoDB for each catalog product. Recommendations settings allow for administration of product recommendations, such as manually assigned recommendations, and the priority of sources used to provide automated recommendations.
862
-
863
- #### Search Products
864
-
865
- To facilitate real-time [search](searching.html), Workarea stores multiple search documents in Elasticsearch for each catalog product. Unlike analytics products and recommendations settings, search product documents are derived directly from the corresponding catalog product documents. [Search models](searching.html#search-models_9) such as `Search::Admin::CatalogProduct` and `Search::Storefront::Product` transform catalog product documents, joining fields within and across models as necessary, producing representations of the products suitable for real-time, full-text search (including matching, filtering, and sorting).
866
-
867
- The various representations of a product are related by catalog product ID. The following example demonstrates these relationships.
868
-
869
- ```ruby
870
- catalog_product_id = "02B81A9D07"
871
-
872
- catalog_product =
873
- Workarea::Catalog::Product.find(catalog_product_id)
874
-
875
- analytics_product =
876
- Workarea::Analytics::Product.find(catalog_product_id)
877
-
878
- recommendations_settings =
879
- Workarea::Recommendations::Settings.find(catalog_product_id)
880
-
881
- search_products =
882
- Workarea.elasticsearch.search(
883
- index: '',
884
- body: {
885
- query: {
886
- match: {
887
- '_id' => "product-#{product_id}"
888
- }
889
- }
890
- })['hits']['hits']
891
- ```
892
-
893
- In the example above, `search_products` returns a collection because there are multiple search products for each catalog product (one for each Elasticsearch index; the exact number depends on several factors, such as the number of configured locales and which plugins are installed). Also note the search product IDs are prepended with `"product-"`. Each Elasticsearch index contains documents derived from various Mongoid document types, so the prefix is necessary to ensure uniqueness.
894
-
895
- Remember, the product representations described in this section are used to determine _which_ products to show to consumers, but they aren't used to _display_ the products. That responsibility belongs to the catalog product documents (and view models).
896
-
897
- ### Product State While Browsing
898
-
899
- As consumers browse the Storefront, the display of products is affected by various application and document states. The current Rails environment, the current locale, and the current site (if multi site) affect which Mongo database and Elasticsearch indexes are queried for products. Furthermore, the state of each Mongo document is affected by current locale and current release (release is applicable only when previewing the Storefront as an admin).
900
-
901
- #### Product Inclusion
902
-
903
- Each of the merchandising subsystems introduced above has its own logic to determine which products are returned for a given query or criteria. In all cases, _inactive products are excluded from results_; that is, they aren't displayed to consumers in the Storefront. A product's activeness is administrable; the product and each of its variants has an `active` field. The value of this field varies by release and locale, so each combination of those application states may produce a different value for `active`. Furthermore, a product is considered active only if one or more of its embedded variants are also active.
904
-
905
- ```ruby
906
- product =
907
- Workarea::Catalog::Product.create(name: 'Keyed Padlock')
908
-
909
- variant =
910
- product.variants.create(sku: 'KEYPAD-S-1-14')
911
-
912
- variant.active?
913
- # => true
914
-
915
- product.active?
916
- # => true
917
-
918
- variant.update_attributes(active: false)
919
-
920
- variant.active?
921
- # => false
922
-
923
- product.active?
924
- # => false
925
- ```
926
-
927
- #### Field Inclusion & Values
928
-
929
- For each product that _is_ displayed, a view model and several partials and UI components are responsible for presenting the product. For example, the following ingredients may go into displaying a product in a browsing context within the Storefront:
930
-
931
- - `Workarea::Storefront::ProductViewModel`
932
- - _workarea/storefront/products/\_summary.html.haml_
933
- - _workarea/storefront/products/\_pricing.html.haml_
934
- - _workarea/storefront/products/\_price.html.haml_
935
- - `.product-summary`
936
- - `.product-prices`
937
-
938
- Each of these is involved in determining which fields are included/excluded and how they are arranged.
939
-
940
- Furthermore, the value of each field is subject to the current locale and current release (if present). The locale affects all internationalized fields, while the release affects nearly all fields.
941
-
942
- #### Primary Image
943
-
944
- Lastly, the image used to represent the product while browsing—the product's primary image—is determined by logic in the view model used to present the product. The behavior may be affected by plugins and extensions, but the default logic is to use the _first_ image, according to the administrable `position` of each image.
945
-
946
- The following example re-uses the product and images created in Catalog Product Images.
947
-
948
- ```ruby
949
- # the product has 2 images
950
- catalog_product.images.map(&:name)
951
- # => ["3_years.jpg", "5_years.jpg"]
952
-
953
- # the "3_years" image is positioned first
954
- catalog_product.images.map(&:position)
955
- # => [0, 1]
956
-
957
- # initialize a Storefront view model
958
- storefront_product =
959
- Workarea::Storefront::ProductViewModel.wrap(catalog_product)
960
-
961
- # the "3_years" image is the primary image
962
- storefront_product.primary_image.name
963
- # => "3_years.jpg"
964
- ```
965
-
966
- ![](images/3-years-primary-image.png)
967
-
968
- ```ruby
969
- # swap the image positions
970
- catalog_product.images.first.update_attributes(position: 1)
971
- catalog_product.images.second.update_attributes(position: 0)
972
- catalog_product.images.map(&:position)
973
- # => [1, 0]
974
-
975
- # re-initialize the view model to simulate a new request
976
- # (primary_image is cached for the duration of each request)
977
- storefront_product =
978
- Workarea::Storefront::ProductViewModel.wrap(catalog_product)
979
-
980
- # now "5_years" is the primary image
981
- storefront_product.primary_image.name
982
- # => "5_years.jpg"
983
- ```
984
-
985
- ![](images/5-years-primary-image.png)
986
-
987
- If the product has no images, the placeholder image is used.
988
-
989
- ```ruby
990
- new_storefront_product =
991
- Workarea::Storefront::ProductViewModel
992
- .wrap(Workarea::Catalog::Product.new)
993
-
994
- new_storefront_product.primary_image.name
995
- # => "product_placeholder.jpg"
996
- ```
997
-
998
- ## Showing Products
999
-
1000
- After browsing to narrow the catalog to a specific product, the _show_, or _detail_, page presents the product to the consumer with additional details: more images, larger images, a full description, recommendations, etc. Refer to Figure 1 for an example. The product show view presents the product's options, allowing the consumer to reduce the product to a specific item for purchase.
1001
-
1002
- ### Product Options
1003
-
1004
- Conceptually, <dfn>product options</dfn> are the distinct values from which a consumer may choose to reduce a product (a group of items) to a specific item (identified by its SKU) for purchase. The options are derived from the collective details of the product's variants, after flattening each member's values. Concretely, in code and UI, the term "options" may refer to several different data structures and UI abstractions, but in each instance, the usage is generally aligned with the concept of product options just described.
1005
-
1006
- Options (for example: Blue, Red, Large, Small) are typically grouped by name or key (for example: Color, Size) and presented as a multi-dimensional matrix, where the intersections represent the uniquely identifiable items that make up the product. To make this concrete, review the Keyed Padlock product introduced above. That product's variants collectively have 6 unique values, organized into 3 groupings.
1007
-
1008
- ```ruby
1009
- option_groupings =
1010
- keyed_padlock.variants.map(&:details).map(&:keys).flatten.uniq.sort
1011
- options =
1012
- keyed_padlock.variants.map(&:details).map(&:values).flatten.uniq.sort
1013
-
1014
- option_groupings.count
1015
- # => 3
1016
-
1017
- puts option_groupings
1018
- # Shackle Diameter
1019
- # Shackle Length
1020
- # Shackle Material
1021
-
1022
- options.count
1023
- # => 6
1024
-
1025
- puts options
1026
- # 1"
1027
- # 1/2"
1028
- # 1/4"
1029
- # 2"
1030
- # Brass
1031
- # Steel
1032
- ```
1033
-
1034
- How these options are presented to consumers varies by template (templates are covered next). The following image shows the product displayed using the option selects template.
1035
-
1036
- ![](images/option-selects-template.png)
1037
-
1038
- Since the data is well designed and managed to this point, selecting a value from each of the 3 selects matches exactly 1 variant within the product. The SKU of that variant is used to identify the item to be purchased if the consumer adds to cart.
1039
-
1040
- ### Product Templates
1041
-
1042
- Each product has an administrable template which is managed by admins and controls the presentation of the product in the Storefront. Specifically, each template is a combination of a view model and partial used to display the product in the Storefront.
1043
-
1044
- Workarea (since v3.3) includes 3 templates: Generic, Option Selects, and Option Thumbnails. However, your application may include more templates, since plugins and applications can add their own templates (see [Add, Remove, or Change a Product Template](add-remove-or-change-a-product-template.html)).
1045
-
1046
- The following snippets provide some examples of how to find which plugins are available to your application and how to find the relevant code for the templates. These examples are for an application with several plugins installed and its own custom "Pre Owned" template.
1047
-
1048
- List the templates offered for each product within the Admin:
1049
-
1050
- ```ruby
1051
- puts Workarea.config.product_templates.sort
1052
- # gift_card
1053
- # option_selects
1054
- # option_thumbnails
1055
- # pre_owned
1056
- # swatches
1057
- # test_product
1058
- ```
1059
-
1060
- From the shell, list all product template view model and partial source code files that exist within your application and the specific version of the platform and plugins you are running. You can also do this search from your editor if that is preferrable.
1061
-
1062
- ```bash
1063
- $ find . $(bundle show --paths) -type f -path '*app*view*workarea*storefront*product*templates*' | grep -o -e 'workarea-.*$' -e '^\..*$' | sort
1064
- ./app/view_models/workarea/storefront/product_templates/pre_owned_view_model.rb
1065
- ./app/views/workarea/storefront/products/templates/_pre_owned.html.haml
1066
- workarea-gift_cards-3.4.0/app/view_models/workarea/storefront/product_templates/gift_card_view_model.rb
1067
- workarea-gift_cards-3.4.0/app/views/workarea/storefront/products/templates/_gift_card.html.haml
1068
- workarea-storefront-3.3.2/app/view_models/workarea/storefront/product_templates/option_selects_view_model.rb
1069
- workarea-storefront-3.3.2/app/view_models/workarea/storefront/product_templates/option_thumbnails_view_model.rb
1070
- workarea-storefront-3.3.2/app/view_models/workarea/storefront/product_templates/test_product_view_model.rb
1071
- workarea-storefront-3.3.2/app/views/workarea/storefront/products/templates/_generic.html.haml
1072
- workarea-storefront-3.3.2/app/views/workarea/storefront/products/templates/_option_selects.html.haml
1073
- workarea-storefront-3.3.2/app/views/workarea/storefront/products/templates/_option_thumbnails.html.haml
1074
- workarea-storefront-3.3.2/app/views/workarea/storefront/products/templates/_test.html.haml
1075
- workarea-swatches-1.0.1/app/view_models/workarea/storefront/product_templates/swatches_view_model.rb
1076
- workarea-swatches-1.0.1/app/views/workarea/storefront/products/templates/_swatches.html.haml
1077
- ```
1078
-
1079
- The Generic template uses the default Storefront view model, while other templates use a more specialized view model that inherits from the default Storefront product view model (for example, Option Selects uses `Storefront::ProductTemplates::OptionSelectsViewModel`).
1080
-
1081
- ### Product State While Showing
1082
-
1083
- Within the Storefront, several states affect the display of a product when showing.
1084
-
1085
- #### Product Display
1086
-
1087
- Whether a product displays at all is affected by its activeness. Consumers cannot view inactive products. Navigating to an inactive product (e.g. from an email or bookmarked URL) results in `InvalidDisplay` (404 response).
1088
-
1089
- ![](images/invalid-display.png)
1090
-
1091
- Admins can view inactive products in the Storefront.
1092
-
1093
- For a product to be considered active, it's `active` field must be `true` and it must have at least one active variant. Remember that the active field's value varies by locale (since Workarea 3.3).
1094
-
1095
- #### Field Inclusion & Values
1096
-
1097
- When showing a product in the Storefront, the product's template affects which fields are included/excluded, their current values, and how they are presented (the overall layout/design for the product).
1098
-
1099
- For each product that _is_ displayed, a view model and several partials and UI components are responsible for presenting the product. For example, the following ingredients may go into displaying a product in a product detail context within the Storefront:
1100
-
1101
- - `Workarea::Storefront::ProductViewModel`
1102
- - _workarea/storefront/products/show.html.haml_
1103
- - _workarea/storefront/products/templates/\_generic.html.haml_
1104
- - _workarea/storefront/products/\_pricing.html.haml_
1105
- - _workarea/storefront/products/\_price.html.haml_
1106
- - `.product-detail-container`
1107
- - `.product-details`
1108
- - `.product-prices`
1109
-
1110
- Each of these is involved in determining which fields are included/excluded and how they are arranged.
1111
-
1112
- Furthermore, the value of each field is subject to the current locale and current release (if present). The locale affects all internationalized fields, while the release affects nearly all fields.
1113
-
1114
- #### Inclusion of Options
1115
-
1116
- Since a product's options are derived from its variants' details, _which options_ are included is determined in part by _which variants_ are included. The Storefront product view model redefines the catalog product's `variants` collection to include only those variants that are active and have displayable inventory (the concept of displayable inventory is outside the scope of this guide). Therefore, variants that are inactive or whose inventory is not displayable are not considered when creating the options for the product.
1117
-
1118
- The following examples demonstrates how the product's variants collection and options are modified when presented for display in the Storefront.
1119
-
1120
- ```ruby
1121
- # find the 'Tropical Drink Mix' product'
1122
- model = Workarea::Catalog::Product.find_by(name: 'Tropical Drink Mix')
1123
- # wrap it in a Storefront view model
1124
- view_model = Workarea::Storefront::ProductViewModel.wrap(model)
1125
-
1126
- # The variants count is the same at this point
1127
- model.variants.count
1128
- # => 3
1129
- view_model.variants.count
1130
- # => 3
1131
- ```
1132
-
1133
- The product therefore has 3 variants and 3 options:
1134
-
1135
- ![](images/3-variants-3-options.png)
1136
-
1137
- ```ruby
1138
- # set one of the variants to inactive
1139
- model.variants.second.update_attributes!(active: false)
1140
- # the model still has 3 variants
1141
- model.variants.count
1142
- # => 3
1143
-
1144
- # re-create the view model (to bust cache)
1145
- view_model = Workarea::Storefront::ProductViewModel.wrap(model)
1146
- # the Storefront view of the product has only 2 variants
1147
- view_model.variants.count
1148
- # => 2
1149
-
1150
- # choose another variant and make the corresponding
1151
- # inventory undisplayable
1152
- model.variants.last.tap do |variant|
1153
- Workarea::Inventory::Sku
1154
- .find(variant.sku)
1155
- .update_attributes!(policy: 'standard', available: '0')
1156
- end
1157
- model.variants.count
1158
- # => 3
1159
-
1160
- # now the Storefront view of the product contains only a single variant
1161
- view_model = Workarea::Storefront::ProductViewModel.wrap(model)
1162
- view_model.variants.count
1163
- # => 1
1164
- ```
1165
-
1166
- Now the product has 3 variants, but only 1 option, so the option select menu is removed in the Storefront:
1167
-
1168
- ![](images/3-variants-1-option.png)
1169
-
1170
- #### Presentation of Options
1171
-
1172
- You saw above an image of the Keyed Padlock product displayed using the Option Selects template, where the options (for example Steel, Brass, 1", 2") are grouped by key (Shackle Material, Shackle Length). In contrast to this, the Generic template groups options by variant, essentially converting the matrix of options into a flat list of items.
1173
-
1174
- ```ruby
1175
- # change the 'Keyed Padlock' product to the generic template
1176
- keyed_padlock =
1177
- Workarea::Catalog::Product.find_by(name: 'Keyed Padlock')
1178
- keyed_padlock
1179
- .update_attributes!(template: 'generic')
1180
- ```
1181
-
1182
- The Keyed Padlock displayed with the Generic template:
1183
-
1184
- ![](images/generic-template.png)
1185
-
1186
- The Option Thumbnails template groups options by details key, like the Option Selects template. But it uses a different UI to present the options, which includes a thumbnail image representing the option, when available.
1187
-
1188
- ```ruby
1189
- # change the 'Extended Service Plan' product
1190
- # to the option thumbnails template
1191
- extended_service_plan =
1192
- Workarea::Catalog::Product.find_by(name: 'Extended Service Plan')
1193
- extended_service_plan
1194
- .update_attributes!(template: 'option_thumbnails')
1195
- ```
1196
-
1197
- An example of Option Thumbnails:
1198
-
1199
- ![](images/option-thumbnails-template.png)
1200
-
1201
- #### Tracking Option State
1202
-
1203
- As a consumer selects options in the Storefront, the UI updates asynchronously. The state of the option selections is stored as params in the URL.
1204
-
1205
- The generic template prefers the `sku` param (e.g. `sku=KEYPAD-S-1-12`, while the other templates prefer params that match specific options (e.g. `Color=Blue,Size=Large`). However, either type of param is respected by all templates. Requesting a product with these URL params will attempt to restore the indicated option state.
1206
-
1207
- #### Presentation of Product Images, Pricing & Inventory
1208
-
1209
- Which images are shown and which image is selected depends on the product template and which options are selected. Remember that each image may be associated with a product option.
1210
-
1211
- The generic template always displays all the product images. The following examples use the Extended Service Plan product from above, shown below using the generic template.
1212
-
1213
- ![](images/generic-product-template-images-no-options-selected.png)
1214
-
1215
- When options are selected, the generic template will try to find images matching those options and will select the first such image. In the following screenshot, the "5 years" option is selected, so the image corresponding to that option is selected.
1216
-
1217
- ![](images/generic-product-template-images-options-selected.png)
1218
-
1219
- Product templates other than generic will show _only_ the images which match the selected options. The screenshot below changes the template to Option Selects. The image matching the selected "5 years" option is selected, and is the only image displayed. The other image does not match this option and is hidden.
1220
-
1221
- ![](images/option-selects-product-template-images-options-selected.png)
1222
-
1223
- When no options are selected in this type of template, only the images that match the options of the product's primary image will be displayed (since Workarea 3.3.2).
1224
-
1225
- The selection of options also affects the display of pricing and inventory. The specifics of pricing and inventory are out of scope for this guide, but notice in the following examples how the selection of options affects the display of pricing and inventory. Once enough options are selected to identify a specific item, the item's SKU is used to look up specific pricing and inventory information. Without a specific SKU, the information is generalized (price ranges) or omitted (inventory).
1226
-
1227
- once the options match a specific sku, we know the exact price for the given sku and quantity
1228
-
1229
- The following example contains price ranges and no inventory status because a specific item has not been selected:
1230
-
1231
- ![](images/price-display-no-options.png)
1232
-
1233
- In the next example a specific item is selected, so distinct pricing and inventory information is shown:
1234
-
1235
- ![](images/price-display-options-selected.png)
1236
-
1237
- #### Product Purchasability
1238
-
1239
- For a product to be purchasable, it must have at least 1 active variant, the inventory related to that variant's SKU must be purchasable, and the pricing related to the variant's SKU must have an active price. When these conditions are not met, the product is displayed, but consumers cannot purchase any of its items:
1240
-
1241
- ![](images/unpurchasable-product.png)
1242
-
1243
- ## Summary
1244
-
1245
- - Workarea groups related buy varying items into catalog products, where the shared details are stored on the product, and the details on which the items vary are stored on embedded variants
1246
- - Each variant stores a SKU, a retailer-provided ID which encodes the variant’s distinct details and identifies the item throughout the Workarea system and across other systems
1247
- - Products also embed images, each of which may be associated with a particular product option (for example, the color _indigo_)
1248
- - Workarea’s inventory, pricing, and shipping subsystems store additional records for each item; records are related by SKU
1249
- - View models “wrap” catalog products, extending the product interface for presentation within a particular context (such as Admin or Storefront); this involves joining the catalog product with related models
1250
- - Administrators manage products and related models through the Admin web interface and data files, which allow import from and export to other software systems or applications
1251
- - Developers can additionally manage the catalog through a command line interface, through extension of the Ruby interface, and using the JSON/HTTP interface provided by the Workarea API plugin
1252
- - Merchandising is a combination of automation and administration which determines the placement of products within the Storefront and entices consumers to buy
1253
- - A variety of application and document states affect the presentation of products to consumers in the Storefront
1254
- - A Storefront product show page presents the product details and options to consumers, so they can narrow the product to a specific item for purchase
1255
-
1256
- ## Notes
1257
-
1258
- [1]&nbsp;If you’re working with a catalog that isn’t organized this way, storing exactly one variant per product may be preferable.
1259
-
1260
- [2]&nbsp;Upcoming additions to this guide will explicitly define and explain the concept of options, and further explore product browsing and showing.
1261
-
1262
- [3]&nbsp;Templates and options will be covered in a future update to this guide.
1263
-
1264
- [4]&nbsp;However, you may want to store the colors as separate values for the product’s filters. Filters will be covered in a forthcoming guide on searching products.
1265
-
1266
- [5]&nbsp;Upcoming additions to this guide will provide additional examples of this in the context of showing products in the Storefront.
1267
-
1268
- [6]&nbsp;You can change the image file used for the product placeholder image. A forthcoming guide on extending product images will provide step-by-step instructions.
1269
-
1270
- [7]&nbsp;A future section on templates will cover additional product view models in the Storefront.