workarea 3.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +326 -0
- data/CHANGELOG.md +20501 -0
- data/README.md +163 -0
- data/docker-compose.yml +27 -0
- data/docs/Gemfile +8 -0
- data/docs/bin/middleman +29 -0
- data/docs/config.rb +87 -0
- data/docs/config.ru +7 -0
- data/docs/data/articles.yml +157 -0
- data/docs/package.json +15 -0
- data/docs/source/404.html.erb +13 -0
- data/docs/source/articles/access-routes-in-javascript.html.md +33 -0
- data/docs/source/articles/add-a-content-area.html.md +169 -0
- data/docs/source/articles/add-a-content-block-type.html.md +334 -0
- data/docs/source/articles/add-a-report.html.md +202 -0
- data/docs/source/articles/add-css-through-the-admin-ui.html.md +30 -0
- data/docs/source/articles/add-javascript-through-a-manifest.html.md +367 -0
- data/docs/source/articles/add-javascript-through-a-view.html.md +80 -0
- data/docs/source/articles/add-javascript-through-the-admin-ui.html.md +30 -0
- data/docs/source/articles/add-metrics.html.md +58 -0
- data/docs/source/articles/add-or-replace-a-pricing-calculator.html.md +150 -0
- data/docs/source/articles/add-remove-or-change-a-mongoid-validation.html.md +147 -0
- data/docs/source/articles/add-remove-or-change-a-product-template.html.md +142 -0
- data/docs/source/articles/add-remove-sort-and-group-storefront-search-filters.html.md +483 -0
- data/docs/source/articles/add-stylesheets-through-a-manifest.html.md +276 -0
- data/docs/source/articles/add-system-content.html.md +138 -0
- data/docs/source/articles/analytics-overview.html.md +51 -0
- data/docs/source/articles/analyze-storefront-search-results.html.md +261 -0
- data/docs/source/articles/api-overview.html.md +35 -0
- data/docs/source/articles/appending.html.md +506 -0
- data/docs/source/articles/application-document.html.md +88 -0
- data/docs/source/articles/automated-javascript-testing.html.md +162 -0
- data/docs/source/articles/b2b-overview.html.md +64 -0
- data/docs/source/articles/browser-and-device-support.html.md +47 -0
- data/docs/source/articles/change-product-placeholder-image.html.md +39 -0
- data/docs/source/articles/change-storefront-search-results.html.md +283 -0
- data/docs/source/articles/change-the-storefront-product-pricing-ui.html.md +348 -0
- data/docs/source/articles/change-the-storefront-search-filters-ui.html.md +103 -0
- data/docs/source/articles/checkout.html.md +479 -0
- data/docs/source/articles/commerce-model.html.md +164 -0
- data/docs/source/articles/configuration-for-hosting.html.md +106 -0
- data/docs/source/articles/configuration.html.md +406 -0
- data/docs/source/articles/configure-a-payment-gateway.html.md +58 -0
- data/docs/source/articles/configure-asset-storage.html.md +29 -0
- data/docs/source/articles/configure-asset-types.html.md +18 -0
- data/docs/source/articles/configure-contact-form-subjects-list.html.md +24 -0
- data/docs/source/articles/configure-imageoptim.html.md +23 -0
- data/docs/source/articles/configure-locales.html.md +45 -0
- data/docs/source/articles/configure-logins-and-authentication.html.md +42 -0
- data/docs/source/articles/configure-low-inventory-threshold.html.md +26 -0
- data/docs/source/articles/configure-product-image-sizes-and-processing.html.md +28 -0
- data/docs/source/articles/content.html.md +554 -0
- data/docs/source/articles/contentable.html.md +41 -0
- data/docs/source/articles/contribute-code.html.md +69 -0
- data/docs/source/articles/contribute-documentation.html.md +60 -0
- data/docs/source/articles/create-a-custom-discount.html.md +234 -0
- data/docs/source/articles/create-a-new-app.html.md +131 -0
- data/docs/source/articles/create-a-plugin.html.md +19 -0
- data/docs/source/articles/create-a-style-guide.html.md +71 -0
- data/docs/source/articles/create-a-theme.html.md +134 -0
- data/docs/source/articles/css-architectural-overview.html.md +89 -0
- data/docs/source/articles/customize-a-helper.html.md +91 -0
- data/docs/source/articles/decoration.html.md +415 -0
- data/docs/source/articles/define-and-configure-inventory-policies.html.md +107 -0
- data/docs/source/articles/documentation-style-guide.html.md +48 -0
- data/docs/source/articles/documentation.html.md +54 -0
- data/docs/source/articles/domain-modeling.html.md +82 -0
- data/docs/source/articles/error-pages.html.md.erb +95 -0
- data/docs/source/articles/extension-overview.html.md +152 -0
- data/docs/source/articles/favicon-support.html.md +112 -0
- data/docs/source/articles/feature-spec-helper-stylesheet.html.md +25 -0
- data/docs/source/articles/featurejs-and-feature-spec-helper.html.md +20 -0
- data/docs/source/articles/help-and-support.html.md +34 -0
- data/docs/source/articles/html-fragment-caching.html.md +46 -0
- data/docs/source/articles/http-caching.html.md +43 -0
- data/docs/source/articles/i18n.html.md +35 -0
- data/docs/source/articles/images-flow.html.md +10 -0
- data/docs/source/articles/index-storefront-search-documents.html.md +104 -0
- data/docs/source/articles/infrastructure.html.md +46 -0
- data/docs/source/articles/installing.html.md +61 -0
- data/docs/source/articles/integrate-a-payment-gateway.html.md +124 -0
- data/docs/source/articles/integrate-a-web-analytics-provider.html.md +35 -0
- data/docs/source/articles/integrate-an-inventory-management-system.html.md +88 -0
- data/docs/source/articles/integrating-with-other-software.html.md +59 -0
- data/docs/source/articles/inventory.html.md +352 -0
- data/docs/source/articles/javascript-coding-standards.html.md +30 -0
- data/docs/source/articles/javascript-modules.html.md +174 -0
- data/docs/source/articles/javascript-overview.html.md +62 -0
- data/docs/source/articles/javascript-reference-documentation.html.md +51 -0
- data/docs/source/articles/javascript-templates.html.md +52 -0
- data/docs/source/articles/low-level-caching.html.md +25 -0
- data/docs/source/articles/maintain-a-plugin.html.md +12 -0
- data/docs/source/articles/maintenance-policy.html.md +79 -0
- data/docs/source/articles/navigable.html.md +51 -0
- data/docs/source/articles/navigating-the-code.html.md +149 -0
- data/docs/source/articles/navigation.html.md +386 -0
- data/docs/source/articles/order-life-cycle.html.md +546 -0
- data/docs/source/articles/order-pricing.html.md +389 -0
- data/docs/source/articles/orders-and-items.html.md +210 -0
- data/docs/source/articles/orders.html.md +66 -0
- data/docs/source/articles/overriding.html.md +155 -0
- data/docs/source/articles/overview.html.md +43 -0
- data/docs/source/articles/plugins-overview.html.md +12 -0
- data/docs/source/articles/prerequisites-and-dependencies.html.md +202 -0
- data/docs/source/articles/products.html.md.erb +1270 -0
- data/docs/source/articles/progressive-web-application-support.html.md +148 -0
- data/docs/source/articles/rails-asset-manifests.html.md +33 -0
- data/docs/source/articles/rails-asset-view-helpers.html.md +25 -0
- data/docs/source/articles/reading-data.html.md +10 -0
- data/docs/source/articles/releasable.html.md +37 -0
- data/docs/source/articles/report-a-bug.html.md +75 -0
- data/docs/source/articles/ruby-coding-standards.html.md +10 -0
- data/docs/source/articles/run-sidekiq-in-a-local-environment.html.md +40 -0
- data/docs/source/articles/searching.html.md +1005 -0
- data/docs/source/articles/security-policy.html.md +42 -0
- data/docs/source/articles/seeds.html.md +345 -0
- data/docs/source/articles/shipping.html.md +756 -0
- data/docs/source/articles/sort-and-exclude-product-options.html.md +47 -0
- data/docs/source/articles/storefront-search-features.html.md +568 -0
- data/docs/source/articles/storefront-searches.html.md +126 -0
- data/docs/source/articles/style-guides.html.md +21 -0
- data/docs/source/articles/stylesheet-coding-standards.html.md +24 -0
- data/docs/source/articles/stylesheets-overview.html.md +67 -0
- data/docs/source/articles/swappable-list-data-structure.html.md +81 -0
- data/docs/source/articles/system-emails.html.md +102 -0
- data/docs/source/articles/taggable.html.md +8 -0
- data/docs/source/articles/test-a-credit-card-transaction.html.md +16 -0
- data/docs/source/articles/test-if-a-plugin-is-installed.html.md +34 -0
- data/docs/source/articles/testing.html.md +914 -0
- data/docs/source/articles/themes-overview.html.md +155 -0
- data/docs/source/articles/translate-administrable-content.html.md +14 -0
- data/docs/source/articles/translate-javascript-content.html.md +16 -0
- data/docs/source/articles/translate-or-customize-message-content.html.md +29 -0
- data/docs/source/articles/translate-or-customize-static-content.html.md +30 -0
- data/docs/source/articles/use-an-existing-workarea-app.html.md +108 -0
- data/docs/source/articles/view-models.html.md +509 -0
- data/docs/source/articles/views.html.md +14 -0
- data/docs/source/articles/workers.html.md +613 -0
- data/docs/source/articles/writing-data.html.md +10 -0
- data/docs/source/cli.html.md +163 -0
- data/docs/source/favicon.ico +0 -0
- data/docs/source/images/3-variants-1-option.png +0 -0
- data/docs/source/images/3-variants-3-options.png +0 -0
- data/docs/source/images/3-years-primary-image.png +0 -0
- data/docs/source/images/404-storefront-error-page.png +0 -0
- data/docs/source/images/404-system-content-admin.png +0 -0
- data/docs/source/images/404.jpg +0 -0
- data/docs/source/images/5-years-primary-image.png +0 -0
- data/docs/source/images/activity-dashboard.png +0 -0
- data/docs/source/images/activity-for-object.png +0 -0
- data/docs/source/images/activity-ui.png +0 -0
- data/docs/source/images/adding-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/adding-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/admin-alerts-ui.png +0 -0
- data/docs/source/images/admin-category-range-filters.png +0 -0
- data/docs/source/images/admin-for-3-column-hero.png +0 -0
- data/docs/source/images/admin-help-index.png +0 -0
- data/docs/source/images/admin-help-ui.png +0 -0
- data/docs/source/images/admin-javascript.png +0 -0
- data/docs/source/images/admin-notification-for-deactivated-discount.png +0 -0
- data/docs/source/images/admin-notifications-ui.png +0 -0
- data/docs/source/images/admin-product-show-page.png +0 -0
- data/docs/source/images/admin-products-index-page.png +0 -0
- data/docs/source/images/admin-range-filters.png +0 -0
- data/docs/source/images/admin-style-guides-navigation.png +0 -0
- data/docs/source/images/after-re-seeding.png +0 -0
- data/docs/source/images/after-seeding-localhost-3000.png +0 -0
- data/docs/source/images/after-seeding.png +0 -0
- data/docs/source/images/arrow.svg +1 -0
- data/docs/source/images/arrow_white.svg +1 -0
- data/docs/source/images/aws-resource-map.png +0 -0
- data/docs/source/images/backordered-until-output-on-inventory-sku-card.png +0 -0
- data/docs/source/images/before-seeding-localhost-3000.png +0 -0
- data/docs/source/images/before-seeding.png +0 -0
- data/docs/source/images/browsing-workarea-versions-on-the-web.png +0 -0
- data/docs/source/images/bulk-asset-upload-on-assets-index-page.png +0 -0
- data/docs/source/images/bulk-asset-upload-while-editing-content.png +0 -0
- data/docs/source/images/bundle-show-workarea-core.png +0 -0
- data/docs/source/images/bundle-show-workarea.png +0 -0
- data/docs/source/images/calendar-for-backordered-until-field.png +0 -0
- data/docs/source/images/captioned-image-block-in-storefront.png +0 -0
- data/docs/source/images/captioned-image-content-block-storefront-component-style-guide.png +0 -0
- data/docs/source/images/cart-system-content-in-admin.png +0 -0
- data/docs/source/images/cart-system-content-in-storefront.png +0 -0
- data/docs/source/images/checkout-addresses-guest.png +0 -0
- data/docs/source/images/checkout-addresses-user.png +0 -0
- data/docs/source/images/checkout-confirmation.png +0 -0
- data/docs/source/images/checkout-flow-0.png +0 -0
- data/docs/source/images/checkout-flow-1.png +0 -0
- data/docs/source/images/checkout-flow-2.png +0 -0
- data/docs/source/images/checkout-flow-3.png +0 -0
- data/docs/source/images/checkout-flow-4.png +0 -0
- data/docs/source/images/checkout-payment-guest.png +0 -0
- data/docs/source/images/checkout-payment-user.png +0 -0
- data/docs/source/images/checkout-shipping.png +0 -0
- data/docs/source/images/color-picker-component-admin-style-guide.png +0 -0
- data/docs/source/images/color-picker-component-on-content-editing-screen.png +0 -0
- data/docs/source/images/commerce-model-carts-orders.png +0 -0
- data/docs/source/images/commerce-model-order-pricing.png +0 -0
- data/docs/source/images/commerce-model.png +0 -0
- data/docs/source/images/configuring-an-index-pattern-in-kibana.png +0 -0
- data/docs/source/images/content-block-presets.png +0 -0
- data/docs/source/images/content-search-customization.png +0 -0
- data/docs/source/images/country-with-region-data-in-address-form.png +0 -0
- data/docs/source/images/country-without-region-data-in-address-form.png +0 -0
- data/docs/source/images/create-content-block-preset-ui.png +0 -0
- data/docs/source/images/credit-card-icons.png +0 -0
- data/docs/source/images/css-added-through-admin.png +0 -0
- data/docs/source/images/css-admin-ui.png +0 -0
- data/docs/source/images/current-configuration-shown-in-admin-settings.png +0 -0
- data/docs/source/images/customer-impersonation-in-admin.png +0 -0
- data/docs/source/images/customer-impersonation-in-store-front.png +0 -0
- data/docs/source/images/date-filter-same-day.png +0 -0
- data/docs/source/images/developer-toolbar-in-store-front.png +0 -0
- data/docs/source/images/discounts-sorted-by-most-redeemed.png +0 -0
- data/docs/source/images/edit-help-article.png +0 -0
- data/docs/source/images/editing-content-for-search-customization.png +0 -0
- data/docs/source/images/editing-dynamic-captioned-image-block.png +0 -0
- data/docs/source/images/editing-product-fields-in-the-admin.png +0 -0
- data/docs/source/images/editing-search-system-content.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/external.svg +1 -0
- data/docs/source/images/favicon_16.png +0 -0
- data/docs/source/images/favicon_180.png +0 -0
- data/docs/source/images/favicon_32.png +0 -0
- data/docs/source/images/filters-all.png +0 -0
- data/docs/source/images/filters-control.png +0 -0
- data/docs/source/images/filters-custom.png +0 -0
- data/docs/source/images/filters-groups.png +0 -0
- data/docs/source/images/filters-material.png +0 -0
- data/docs/source/images/filters-omitted.png +0 -0
- data/docs/source/images/filters-pinned.png +0 -0
- data/docs/source/images/filters-range.png +0 -0
- data/docs/source/images/filters-sorted.png +0 -0
- data/docs/source/images/filters-wrapping-to-second-line-in-admin.png +0 -0
- data/docs/source/images/generic-product-template-images-no-options-selected.png +0 -0
- data/docs/source/images/generic-product-template-images-options-selected.png +0 -0
- data/docs/source/images/generic-template.png +0 -0
- data/docs/source/images/hosting.svg +1 -0
- data/docs/source/images/image-group-content-block-in-storefront.png +0 -0
- data/docs/source/images/images.svg +1 -0
- data/docs/source/images/import-export-screenshot.png +0 -0
- data/docs/source/images/invalid-display.png +0 -0
- data/docs/source/images/itcss.png +0 -0
- data/docs/source/images/kibana-dev-tools-console.png +0 -0
- data/docs/source/images/layout-content-admin-with-2-areas.png +0 -0
- data/docs/source/images/layout-content-admin-with-3-areas.png +0 -0
- data/docs/source/images/link-to-search-system-content.png +0 -0
- data/docs/source/images/logo.svg +1 -0
- data/docs/source/images/menu.svg +2 -0
- data/docs/source/images/mongo-replica-set.svg +1 -0
- data/docs/source/images/multi-column-hero-blocks.png +0 -0
- data/docs/source/images/option-selects-product-template-images-options-selected.png +0 -0
- data/docs/source/images/option-selects-template.png +0 -0
- data/docs/source/images/option-thumbnails-template.png +0 -0
- data/docs/source/images/order-item-total-price-diagram.png +0 -0
- data/docs/source/images/order-pricing-cart-example.png +0 -0
- data/docs/source/images/order-pricing-example-adjustments.png +0 -0
- data/docs/source/images/order-pricing-example-totals.png +0 -0
- data/docs/source/images/order-pricing-placed-order-example.png +0 -0
- data/docs/source/images/order-shipping-total-diagram.png +0 -0
- data/docs/source/images/order-show-with-multiple-tenders.png +0 -0
- data/docs/source/images/order-subtotal-price-diagram.png +0 -0
- data/docs/source/images/order-tax-total-diagram.png +0 -0
- data/docs/source/images/order-total-price-diagram.png +0 -0
- data/docs/source/images/order-total-value-diagram.png +0 -0
- data/docs/source/images/orders-dashboard-links.png +0 -0
- data/docs/source/images/oval.svg +1 -0
- data/docs/source/images/payment-icon-storefront-style-guide.png +0 -0
- data/docs/source/images/people-dashboard-links.png +0 -0
- data/docs/source/images/price-adjustments-diagram.png +0 -0
- data/docs/source/images/price-display-no-options.png +0 -0
- data/docs/source/images/price-display-options-selected.png +0 -0
- data/docs/source/images/pricing-calculators-diagram.png +0 -0
- data/docs/source/images/product-list-content-block-admin.png +0 -0
- data/docs/source/images/product-list-content-block-in-store-front.png +0 -0
- data/docs/source/images/promo-products-excluded-autocomplete-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-featured-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-recommendations-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-results-after.png +0 -0
- data/docs/source/images/promo-products-included-autocomplete-results-before.png +0 -0
- data/docs/source/images/promo-products-included-featured-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-recommendations-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-results-before.png +0 -0
- data/docs/source/images/rails-version-constraint.png +0 -0
- data/docs/source/images/re-enable-discount.png +0 -0
- data/docs/source/images/reading-data.svg +1 -0
- data/docs/source/images/readme-hero.png +0 -0
- data/docs/source/images/redesigned-customized-sort-for-search-results.png +0 -0
- data/docs/source/images/reviews-summary-above-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-below-product-name.png +0 -0
- data/docs/source/images/reviews-summary-below-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-removed.png +0 -0
- data/docs/source/images/rsa-fingerprint-for-stash.png +0 -0
- data/docs/source/images/ruby-version-constraint.png +0 -0
- data/docs/source/images/script-tag-added-through-admin.png +0 -0
- data/docs/source/images/search-analysis-admin-alternate-rendering.png +0 -0
- data/docs/source/images/search-analysis-admin.png +0 -0
- data/docs/source/images/search-quality-report.png +0 -0
- data/docs/source/images/search.svg +1 -0
- data/docs/source/images/searching-for-cart-system-content-in-admin.png +0 -0
- data/docs/source/images/searching-for-layout-system-content-in-admin.png +0 -0
- data/docs/source/images/seeded-admin.png +0 -0
- data/docs/source/images/seeds-from-plugins.png +0 -0
- data/docs/source/images/seo-metadata-automation-ui.png +0 -0
- data/docs/source/images/show-password-button.png +0 -0
- data/docs/source/images/storefront-autocomplete.png +0 -0
- data/docs/source/images/storefront-category-summary-content-block.png +0 -0
- data/docs/source/images/storefront-category.png +0 -0
- data/docs/source/images/storefront-product-after-overriding.png +0 -0
- data/docs/source/images/storefront-product-before-overriding.png +0 -0
- data/docs/source/images/storefront-product-browse-page.png +0 -0
- data/docs/source/images/storefront-product-recommendations.png +0 -0
- data/docs/source/images/storefront-product-show-page.png +0 -0
- data/docs/source/images/storefront-requests-and-search-requests.png +0 -0
- data/docs/source/images/storefront-search-request-handling.png +0 -0
- data/docs/source/images/storefront-search-response-creation.png +0 -0
- data/docs/source/images/storefront-search.png +0 -0
- data/docs/source/images/storefront-style-guides-navigation.png +0 -0
- data/docs/source/images/styles.css +3 -0
- data/docs/source/images/tax-categories-ui.png +0 -0
- data/docs/source/images/tax-rates-ui.png +0 -0
- data/docs/source/images/unpurchasable-product.png +0 -0
- data/docs/source/images/url-redirects-filtering.png +0 -0
- data/docs/source/images/utility-nav-area-in-admin.png +0 -0
- data/docs/source/images/utility-nav-area-in-storefront.png +0 -0
- data/docs/source/images/validation-message-in-storefront.png +0 -0
- data/docs/source/images/view-model-interface.png +0 -0
- data/docs/source/images/viewing-workarea-version-in-source.png +0 -0
- data/docs/source/images/workarea.svg +1 -0
- data/docs/source/images/worst-performing-searches-on-results-customization-page.png +0 -0
- data/docs/source/images/writing-data.svg +1 -0
- data/docs/source/index.html.erb +167 -0
- data/docs/source/javascripts/jquery.js +2 -0
- data/docs/source/javascripts/lunr.js +7 -0
- data/docs/source/javascripts/site.js +299 -0
- data/docs/source/javascripts/vendor/highlight.pack.js +2 -0
- data/docs/source/layouts/article.erb +106 -0
- data/docs/source/layouts/bare.erb +46 -0
- data/docs/source/layouts/layout.erb +43 -0
- data/docs/source/release-notes.html.md +258 -0
- data/docs/source/release-notes/workarea-3-0-0.html.md +146 -0
- data/docs/source/release-notes/workarea-3-0-1.html.md +161 -0
- data/docs/source/release-notes/workarea-3-0-10.html.md +39 -0
- data/docs/source/release-notes/workarea-3-0-11.html.md +277 -0
- data/docs/source/release-notes/workarea-3-0-12.html.md +14 -0
- data/docs/source/release-notes/workarea-3-0-13.html.md +153 -0
- data/docs/source/release-notes/workarea-3-0-14.html.md +93 -0
- data/docs/source/release-notes/workarea-3-0-15.html.md +107 -0
- data/docs/source/release-notes/workarea-3-0-16.html.md +36 -0
- data/docs/source/release-notes/workarea-3-0-17.html.md +141 -0
- data/docs/source/release-notes/workarea-3-0-18.html.md +123 -0
- data/docs/source/release-notes/workarea-3-0-19.html.md +160 -0
- data/docs/source/release-notes/workarea-3-0-2.html.md +222 -0
- data/docs/source/release-notes/workarea-3-0-20.html.md +95 -0
- data/docs/source/release-notes/workarea-3-0-21.html.md +168 -0
- data/docs/source/release-notes/workarea-3-0-22.html.md +268 -0
- data/docs/source/release-notes/workarea-3-0-23.html.md +173 -0
- data/docs/source/release-notes/workarea-3-0-24.html.md +19 -0
- data/docs/source/release-notes/workarea-3-0-25.html.md +26 -0
- data/docs/source/release-notes/workarea-3-0-26.html.md +199 -0
- data/docs/source/release-notes/workarea-3-0-27.html.md +113 -0
- data/docs/source/release-notes/workarea-3-0-28.html.md +39 -0
- data/docs/source/release-notes/workarea-3-0-29.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-3.html.md +35 -0
- data/docs/source/release-notes/workarea-3-0-30.html.md +186 -0
- data/docs/source/release-notes/workarea-3-0-31.html.md +125 -0
- data/docs/source/release-notes/workarea-3-0-32.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-33.html.md +137 -0
- data/docs/source/release-notes/workarea-3-0-34.html.md +203 -0
- data/docs/source/release-notes/workarea-3-0-35.html.md +205 -0
- data/docs/source/release-notes/workarea-3-0-36.html.md +105 -0
- data/docs/source/release-notes/workarea-3-0-37.html.md +144 -0
- data/docs/source/release-notes/workarea-3-0-38.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-39.html.md +77 -0
- data/docs/source/release-notes/workarea-3-0-4.html.md +14 -0
- data/docs/source/release-notes/workarea-3-0-40.html.md +130 -0
- data/docs/source/release-notes/workarea-3-0-41.html.md +70 -0
- data/docs/source/release-notes/workarea-3-0-42.html.md +52 -0
- data/docs/source/release-notes/workarea-3-0-43.html.md +72 -0
- data/docs/source/release-notes/workarea-3-0-44.html.md +93 -0
- data/docs/source/release-notes/workarea-3-0-45.html.md +61 -0
- data/docs/source/release-notes/workarea-3-0-46.html.md +171 -0
- data/docs/source/release-notes/workarea-3-0-47.html.md +130 -0
- data/docs/source/release-notes/workarea-3-0-48.html.md +160 -0
- data/docs/source/release-notes/workarea-3-0-49.html.md +28 -0
- data/docs/source/release-notes/workarea-3-0-5.html.md +225 -0
- data/docs/source/release-notes/workarea-3-0-50.html.md +74 -0
- data/docs/source/release-notes/workarea-3-0-51.html.md +61 -0
- data/docs/source/release-notes/workarea-3-0-52.html.md +76 -0
- data/docs/source/release-notes/workarea-3-0-53.html.md +126 -0
- data/docs/source/release-notes/workarea-3-0-54.html.md +112 -0
- data/docs/source/release-notes/workarea-3-0-55.html.md +105 -0
- data/docs/source/release-notes/workarea-3-0-56.html.md +56 -0
- data/docs/source/release-notes/workarea-3-0-57.html.md +82 -0
- data/docs/source/release-notes/workarea-3-0-58.html.md +153 -0
- data/docs/source/release-notes/workarea-3-0-59.html.md +78 -0
- data/docs/source/release-notes/workarea-3-0-6.html.md +165 -0
- data/docs/source/release-notes/workarea-3-0-60.html.md +43 -0
- data/docs/source/release-notes/workarea-3-0-61.html.md +46 -0
- data/docs/source/release-notes/workarea-3-0-62.html.md +23 -0
- data/docs/source/release-notes/workarea-3-0-63.html.md +25 -0
- data/docs/source/release-notes/workarea-3-0-64.html.md +25 -0
- data/docs/source/release-notes/workarea-3-0-65.html.md +37 -0
- data/docs/source/release-notes/workarea-3-0-7.html.md +207 -0
- data/docs/source/release-notes/workarea-3-0-8.html.md +337 -0
- data/docs/source/release-notes/workarea-3-0-9.html.md +196 -0
- data/docs/source/release-notes/workarea-3-1-0.html.md +414 -0
- data/docs/source/release-notes/workarea-3-1-1.html.md +139 -0
- data/docs/source/release-notes/workarea-3-1-10.html.md +19 -0
- data/docs/source/release-notes/workarea-3-1-11.html.md +27 -0
- data/docs/source/release-notes/workarea-3-1-12.html.md +216 -0
- data/docs/source/release-notes/workarea-3-1-13.html.md +113 -0
- data/docs/source/release-notes/workarea-3-1-14.html.md +39 -0
- data/docs/source/release-notes/workarea-3-1-15.html.md +107 -0
- data/docs/source/release-notes/workarea-3-1-16.html.md +188 -0
- data/docs/source/release-notes/workarea-3-1-17.html.md +141 -0
- data/docs/source/release-notes/workarea-3-1-18.html.md +73 -0
- data/docs/source/release-notes/workarea-3-1-19.html.md +137 -0
- data/docs/source/release-notes/workarea-3-1-2.html.md +55 -0
- data/docs/source/release-notes/workarea-3-1-20.html.md +203 -0
- data/docs/source/release-notes/workarea-3-1-21.html.md +205 -0
- data/docs/source/release-notes/workarea-3-1-22.html.md +121 -0
- data/docs/source/release-notes/workarea-3-1-23.html.md +144 -0
- data/docs/source/release-notes/workarea-3-1-24.html.md +94 -0
- data/docs/source/release-notes/workarea-3-1-25.html.md +77 -0
- data/docs/source/release-notes/workarea-3-1-26.html.md +130 -0
- data/docs/source/release-notes/workarea-3-1-27.html.md +70 -0
- data/docs/source/release-notes/workarea-3-1-28.html.md +52 -0
- data/docs/source/release-notes/workarea-3-1-29.html.md +44 -0
- data/docs/source/release-notes/workarea-3-1-3.html.md +185 -0
- data/docs/source/release-notes/workarea-3-1-30.html.md +72 -0
- data/docs/source/release-notes/workarea-3-1-31.html.md +93 -0
- data/docs/source/release-notes/workarea-3-1-32.html.md +61 -0
- data/docs/source/release-notes/workarea-3-1-33.html.md +171 -0
- data/docs/source/release-notes/workarea-3-1-34.html.md +130 -0
- data/docs/source/release-notes/workarea-3-1-35.html.md +179 -0
- data/docs/source/release-notes/workarea-3-1-36.html.md +28 -0
- data/docs/source/release-notes/workarea-3-1-37.html.md +74 -0
- data/docs/source/release-notes/workarea-3-1-38.html.md +61 -0
- data/docs/source/release-notes/workarea-3-1-39.html.md +96 -0
- data/docs/source/release-notes/workarea-3-1-4.html.md +148 -0
- data/docs/source/release-notes/workarea-3-1-40.html.md +126 -0
- data/docs/source/release-notes/workarea-3-1-41.html.md +128 -0
- data/docs/source/release-notes/workarea-3-1-42.html.md +105 -0
- data/docs/source/release-notes/workarea-3-1-43.html.md +37 -0
- data/docs/source/release-notes/workarea-3-1-44.html.md +82 -0
- data/docs/source/release-notes/workarea-3-1-45.html.md +153 -0
- data/docs/source/release-notes/workarea-3-1-46.html.md +91 -0
- data/docs/source/release-notes/workarea-3-1-47.html.md +65 -0
- data/docs/source/release-notes/workarea-3-1-48.html.md +46 -0
- data/docs/source/release-notes/workarea-3-1-49.html.md +23 -0
- data/docs/source/release-notes/workarea-3-1-5.html.md +169 -0
- data/docs/source/release-notes/workarea-3-1-50.html.md +42 -0
- data/docs/source/release-notes/workarea-3-1-51.html.md +25 -0
- data/docs/source/release-notes/workarea-3-1-52.html.md +57 -0
- data/docs/source/release-notes/workarea-3-1-6.html.md +117 -0
- data/docs/source/release-notes/workarea-3-1-7.html.md +176 -0
- data/docs/source/release-notes/workarea-3-1-8.html.md +283 -0
- data/docs/source/release-notes/workarea-3-1-9.html.md +212 -0
- data/docs/source/release-notes/workarea-3-2-0.html.md +1705 -0
- data/docs/source/release-notes/workarea-3-2-1.html.md +216 -0
- data/docs/source/release-notes/workarea-3-2-10.html.md +237 -0
- data/docs/source/release-notes/workarea-3-2-11.html.md +121 -0
- data/docs/source/release-notes/workarea-3-2-12.html.md +145 -0
- data/docs/source/release-notes/workarea-3-2-13.html.md +138 -0
- data/docs/source/release-notes/workarea-3-2-14.html.md +77 -0
- data/docs/source/release-notes/workarea-3-2-15.html.md +130 -0
- data/docs/source/release-notes/workarea-3-2-16.html.md +111 -0
- data/docs/source/release-notes/workarea-3-2-17.html.md +52 -0
- data/docs/source/release-notes/workarea-3-2-18.html.md +44 -0
- data/docs/source/release-notes/workarea-3-2-19.html.md +72 -0
- data/docs/source/release-notes/workarea-3-2-2.html.md +145 -0
- data/docs/source/release-notes/workarea-3-2-20.html.md +93 -0
- data/docs/source/release-notes/workarea-3-2-21.html.md +61 -0
- data/docs/source/release-notes/workarea-3-2-22.html.md +154 -0
- data/docs/source/release-notes/workarea-3-2-23.html.md +130 -0
- data/docs/source/release-notes/workarea-3-2-24.html.md +200 -0
- data/docs/source/release-notes/workarea-3-2-25.html.md +28 -0
- data/docs/source/release-notes/workarea-3-2-26.html.md +94 -0
- data/docs/source/release-notes/workarea-3-2-27.html.md +61 -0
- data/docs/source/release-notes/workarea-3-2-28.html.md +96 -0
- data/docs/source/release-notes/workarea-3-2-29.html.md +126 -0
- data/docs/source/release-notes/workarea-3-2-30.html.md +112 -0
- data/docs/source/release-notes/workarea-3-2-31.html.md +105 -0
- data/docs/source/release-notes/workarea-3-2-32.html.md +56 -0
- data/docs/source/release-notes/workarea-3-2-33.html.md +82 -0
- data/docs/source/release-notes/workarea-3-2-34.html.md +153 -0
- data/docs/source/release-notes/workarea-3-2-35.html.md +91 -0
- data/docs/source/release-notes/workarea-3-2-36.html.md +118 -0
- data/docs/source/release-notes/workarea-3-2-37.html.md +46 -0
- data/docs/source/release-notes/workarea-3-2-38.html.md +23 -0
- data/docs/source/release-notes/workarea-3-2-39.html.md +42 -0
- data/docs/source/release-notes/workarea-3-2-4.html.md +109 -0
- data/docs/source/release-notes/workarea-3-2-40.html.md +25 -0
- data/docs/source/release-notes/workarea-3-2-41.html.md +90 -0
- data/docs/source/release-notes/workarea-3-2-5.html.md +186 -0
- data/docs/source/release-notes/workarea-3-2-6.html.md +173 -0
- data/docs/source/release-notes/workarea-3-2-7.html.md +89 -0
- data/docs/source/release-notes/workarea-3-2-8.html.md +137 -0
- data/docs/source/release-notes/workarea-3-2-9.html.md +219 -0
- data/docs/source/release-notes/workarea-3-3-0.html.md +1272 -0
- data/docs/source/release-notes/workarea-3-3-1.html.md +324 -0
- data/docs/source/release-notes/workarea-3-3-10.html.md +69 -0
- data/docs/source/release-notes/workarea-3-3-11.html.md +72 -0
- data/docs/source/release-notes/workarea-3-3-12.html.md +136 -0
- data/docs/source/release-notes/workarea-3-3-13.html.md +61 -0
- data/docs/source/release-notes/workarea-3-3-14.html.md +196 -0
- data/docs/source/release-notes/workarea-3-3-15.html.md +167 -0
- data/docs/source/release-notes/workarea-3-3-16.html.md +234 -0
- data/docs/source/release-notes/workarea-3-3-17.html.md +82 -0
- data/docs/source/release-notes/workarea-3-3-18.html.md +165 -0
- data/docs/source/release-notes/workarea-3-3-19.html.md +106 -0
- data/docs/source/release-notes/workarea-3-3-2.html.md +72 -0
- data/docs/source/release-notes/workarea-3-3-20.html.md +116 -0
- data/docs/source/release-notes/workarea-3-3-21.html.md +228 -0
- data/docs/source/release-notes/workarea-3-3-22.html.md +125 -0
- data/docs/source/release-notes/workarea-3-3-23.html.md +154 -0
- data/docs/source/release-notes/workarea-3-3-24.html.md +70 -0
- data/docs/source/release-notes/workarea-3-3-25.html.md +114 -0
- data/docs/source/release-notes/workarea-3-3-26.html.md +260 -0
- data/docs/source/release-notes/workarea-3-3-27.html.md +138 -0
- data/docs/source/release-notes/workarea-3-3-28.html.md +147 -0
- data/docs/source/release-notes/workarea-3-3-29.html.md +63 -0
- data/docs/source/release-notes/workarea-3-3-3.html.md +153 -0
- data/docs/source/release-notes/workarea-3-3-30.html.md +102 -0
- data/docs/source/release-notes/workarea-3-3-31.html.md +57 -0
- data/docs/source/release-notes/workarea-3-3-32.html.md +44 -0
- data/docs/source/release-notes/workarea-3-3-33.html.md +114 -0
- data/docs/source/release-notes/workarea-3-3-4.html.md +332 -0
- data/docs/source/release-notes/workarea-3-3-5.html.md +242 -0
- data/docs/source/release-notes/workarea-3-3-6.html.md +100 -0
- data/docs/source/release-notes/workarea-3-3-7.html.md +148 -0
- data/docs/source/release-notes/workarea-3-3-8.html.md +163 -0
- data/docs/source/release-notes/workarea-3-3-9.html.md +93 -0
- data/docs/source/release-notes/workarea-3-4-0.html.md +580 -0
- data/docs/source/release-notes/workarea-3-4-1.html.md +150 -0
- data/docs/source/release-notes/workarea-3-4-10.html.md +72 -0
- data/docs/source/release-notes/workarea-3-4-11.html.md +60 -0
- data/docs/source/release-notes/workarea-3-4-12.html.md +155 -0
- data/docs/source/release-notes/workarea-3-4-2.html.md +188 -0
- data/docs/source/release-notes/workarea-3-4-3.html.md +136 -0
- data/docs/source/release-notes/workarea-3-4-4.html.md +114 -0
- data/docs/source/release-notes/workarea-3-4-5.html.md +275 -0
- data/docs/source/release-notes/workarea-3-4-6.html.md +169 -0
- data/docs/source/release-notes/workarea-3-4-7.html.md +162 -0
- data/docs/source/release-notes/workarea-3-4-8.html.md +95 -0
- data/docs/source/release-notes/workarea-3-4-9.html.md +135 -0
- data/docs/source/search.html.erb +34 -0
- data/docs/source/shared/_header.erb +61 -0
- data/docs/source/shared/_svgs.erb +17 -0
- data/docs/source/style_guide/index.html.erb +382 -0
- data/docs/source/stylesheets/_base.scss +125 -0
- data/docs/source/stylesheets/_components.scss +669 -0
- data/docs/source/stylesheets/_helpers.scss +10 -0
- data/docs/source/stylesheets/_opinions.scss +42 -0
- data/docs/source/stylesheets/_settings.scss +56 -0
- data/docs/source/stylesheets/_typography.scss +119 -0
- data/docs/source/stylesheets/site.css.scss +14 -0
- data/docs/source/stylesheets/vendor/_avalanche.scss +328 -0
- data/docs/source/stylesheets/vendor/_normalize.scss +341 -0
- data/docs/source/stylesheets/vendor/highlight/_tomorrow_night_blue.scss +75 -0
- data/docs/source/upgrade-guides.html.md +18 -0
- data/docs/source/upgrade-guides/workarea-3-4-0.html.md +152 -0
- data/docs/workarea_renderer.rb +8 -0
- data/docs/yarn.lock +2522 -0
- metadata +669 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
---
|
2
|
+
title: Installing
|
3
|
+
created_at: 2019/05/29
|
4
|
+
excerpt: A guide on the Workarea install script.
|
5
|
+
---
|
6
|
+
|
7
|
+
# Installing
|
8
|
+
|
9
|
+
Workarea is a large Rails engine that requires a few things out of a Rails app it's installed into. This guide will walk you through the details of running `bin/rails generate workarea:install` so you know what changes are being made and why.
|
10
|
+
|
11
|
+
### `application.rb`
|
12
|
+
|
13
|
+
First, this will require the Workarea gems in your `config/application.rb` file. This is done to ensure Workarea can control the environment your application is run in for the purposes of testing and rake tasks.
|
14
|
+
|
15
|
+
### `routes.rb`
|
16
|
+
|
17
|
+
The install generator will mount the three main engines that workarea is built on within your `config/routes.rb` file.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
Rails.application.routes.draw do
|
21
|
+
mount Workarea::Core::Engine => '/'
|
22
|
+
mount Workarea::Admin::Engine => '/admin', as: 'admin'
|
23
|
+
mount Workarea::Storefront::Engine => '/', as: 'storefront'
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
### `workarea.rb`
|
28
|
+
|
29
|
+
An initializer will be created at `config/initializers/workarea.rb`. This serves that the main location for modifying configuration for Workarea. The generator will add some default information based on the name of your application such as `site_name`, `host`, `email_from`, and `email_to`. These serve as critical pieces of information for Workarea to know in order to start the application. Be sure to address the `TODO`s in the file and add the correct production information before deploying to a live environment.
|
30
|
+
|
31
|
+
### `development.rb`
|
32
|
+
|
33
|
+
Workarea relies on [Sidekiq](https://github.com/mperham/sidekiq) for running background jobs. For development, the install generator will add the following line of code to your `config/environments/development.rb` to alleviate the need for sidekiq to be running while in development.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'sidekiq/testing/inline'
|
37
|
+
```
|
38
|
+
|
39
|
+
This tells sidekiq to run workers in process while working locally.
|
40
|
+
|
41
|
+
### `puma.rb`
|
42
|
+
|
43
|
+
Workarea provides puma configuration out of the box, and the install generator will replace the default rails-generated `config/puma.rb` with the following:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require 'workarea/configuration/puma'
|
47
|
+
Workarea::Configuration::Puma.load(self)
|
48
|
+
```
|
49
|
+
This configuration class allows for customizing the puma configuration through environment variables, eliminating the need to add custom configuration files for each environment.
|
50
|
+
|
51
|
+
### `test_helper.rb`
|
52
|
+
|
53
|
+
Workarea provides robust [testing configuration](testing.html) for consistent and easy testing. The install generator will add `require workarea/test_help.rb` to your existing `test/test_helper.rb` file.
|
54
|
+
|
55
|
+
### `favicon.ico`
|
56
|
+
|
57
|
+
Workarea provides [favicon support](favicon-support.html) through content assets within the admin UI. As a result, the install generator removes the `public/favicon.ico` file generated with a new rails application so that it does not interfere with that functionality.
|
58
|
+
|
59
|
+
### `seeds.rb`
|
60
|
+
|
61
|
+
Workarea provides a large set of [seed data](seeds.html) to get your application started. The install generator adds the `db/seeds.rb` file so that you can run seeds like any other rails application.
|
@@ -0,0 +1,124 @@
|
|
1
|
+
---
|
2
|
+
title: Integrate a Payment Gateway
|
3
|
+
excerpt: Workarea uses the ActiveMerchant gem for integration with payment gateways. This gem consolidates gateway functionalities under a common interface.
|
4
|
+
---
|
5
|
+
|
6
|
+
# Integrate a Payment Gateway
|
7
|
+
|
8
|
+
Workarea uses the ActiveMerchant gem for integration with payment gateways. This gem consolidates gateway functionalities under a common interface.
|
9
|
+
|
10
|
+
**Note:** Different gateways offer different functionality under different names!
|
11
|
+
|
12
|
+
Because of the variance in payment gateways, you will probably need to tailor your installation to the gateway. Fortunately, Workarea consolidates gateway knowledge into the `Workarea::Payment::StoreCreditCard` class. This class is responsible for representing a credit card on the gateway. On that class is a single method the system uses to save it on the gateway (get a token to use to reference the card from now on).
|
13
|
+
|
14
|
+
**Note:** The Workarea platform out-of-the-box requires a gateway that supports tokenization! This is done for security. Please ensure your gateway supports this functionality.
|
15
|
+
|
16
|
+
Here is the out of the box implementation of saving the card on the gateway, presented for reference. The `#save!` method is called when the system needs to persist a credit card to be referenced later.
|
17
|
+
|
18
|
+
workarea-core/app/models/workarea/payment/store\_credit\_card.rb :
|
19
|
+
|
20
|
+
```
|
21
|
+
module Workarea
|
22
|
+
class Payment
|
23
|
+
class StoreCreditCard
|
24
|
+
include CreditCardOperation
|
25
|
+
|
26
|
+
def initialize(credit_card, options = {})
|
27
|
+
@credit_card = credit_card
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform!
|
32
|
+
return true if @credit_card.token.present?
|
33
|
+
|
34
|
+
response = handle_active_merchant_errors do
|
35
|
+
gateway.store(@credit_card.to_active_merchant)
|
36
|
+
end
|
37
|
+
|
38
|
+
@credit_card.token = response.params['billingid']
|
39
|
+
end
|
40
|
+
|
41
|
+
def save!
|
42
|
+
perform!
|
43
|
+
@credit_card.save
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Error handling for all communication to the gateway is consolidated within a single module, and then included for all operations to ensure consistent handling of possible errors. You see this in action with the call to `#handle_active_merchant_errors` above. The full implmentation is below for reference.
|
51
|
+
|
52
|
+
workarea-core/app/models/workarea/payment/credit\_card\_operation.rb :
|
53
|
+
|
54
|
+
```
|
55
|
+
module Workarea
|
56
|
+
class Payment
|
57
|
+
module CreditCardOperation
|
58
|
+
def handle_active_merchant_errors
|
59
|
+
begin
|
60
|
+
yield
|
61
|
+
rescue ActiveMerchant::ResponseError => error
|
62
|
+
error.response
|
63
|
+
rescue ActiveMerchant::ActiveMerchantError,
|
64
|
+
ActiveMerchant::ConnectionError => error
|
65
|
+
ActiveMerchant::Billing::Response.new(false, nil)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def gateway
|
70
|
+
Workarea.config.gateways.credit_card
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
After customizing these classes, you may need to customize how this token is used with the gateway. There are a number of places for this:
|
78
|
+
|
79
|
+
- `Workarea::Payment::Authorize::CreditCard`
|
80
|
+
- `Workarea::Payment::Capture::CreditCard`
|
81
|
+
- `Workarea::Payment::Purchase::CreditCard`
|
82
|
+
- `Workarea::Payment::Refund::CreditCard`
|
83
|
+
|
84
|
+
Each of these responds to the `#complete!` method, which should implement performing the respective operation on the gateway. Out of the box implementation for purchase:
|
85
|
+
|
86
|
+
workarea-core/app/models/workarea/purchase/credit\_card.rb :
|
87
|
+
|
88
|
+
```
|
89
|
+
module Workarea
|
90
|
+
class Payment
|
91
|
+
module Purchase
|
92
|
+
class CreditCard
|
93
|
+
include OperationImplementation
|
94
|
+
include CreditCardOperation
|
95
|
+
|
96
|
+
def complete!
|
97
|
+
# Some gateways will tokenize in the same request as the auth/capture.
|
98
|
+
# If that is the case for the gateway you are implementing, omit the
|
99
|
+
# following line, and save the token on the tender after doing the
|
100
|
+
# gateway authorization.
|
101
|
+
return unless StoreCreditCard.new(tender, options).save!
|
102
|
+
|
103
|
+
transaction.response = handle_active_merchant_errors do
|
104
|
+
gateway.purchase(
|
105
|
+
transaction.amount.cents,
|
106
|
+
tender.to_active_merchant
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def cancel!
|
112
|
+
return unless transaction.success?
|
113
|
+
|
114
|
+
transaction.cancellation = handle_active_merchant_errors do
|
115
|
+
gateway.void(transaction.response.params['authorization'])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
---
|
2
|
+
title: Integrate a Web Analytics Provider
|
3
|
+
excerpt: Workarea analytics adapters are responsible for registering callbacks for events and in turn sending the correctly formatted data and events to the third party.
|
4
|
+
---
|
5
|
+
|
6
|
+
# Integrate a Web Analytics Provider
|
7
|
+
|
8
|
+
[Workarea analytics](analytics-overview.html) adapters are responsible for registering callbacks for events and in turn sending the correctly formatted data and events to the third party.
|
9
|
+
|
10
|
+
## Example Adapter
|
11
|
+
|
12
|
+
The easiest way to understand how an adapter is implemented is to look at an example. The Workarea platform includes an official Google Analytics plugin, which acts as a Workarea analytics adapter for Google Analytics. Unpack the gem to view its source.
|
13
|
+
|
14
|
+
```bash
|
15
|
+
gem unpack workarea-google_analytics
|
16
|
+
```
|
17
|
+
|
18
|
+
## Adapter Template
|
19
|
+
|
20
|
+
Below is a commented template for an analytics adapter.
|
21
|
+
|
22
|
+
```javascript
|
23
|
+
// pass a function that will be invoked by the analtyics framework
|
24
|
+
WORKAREA.analytics.registerAdapter('myNewAdapter', function () {
|
25
|
+
// private methods may be included here
|
26
|
+
// return a hash of callbacks for analytics events
|
27
|
+
return {
|
28
|
+
'pageView': function () { /* pageView calls do not have a payload */ },
|
29
|
+
'categoryView': function (payload) { /* send payload */ },
|
30
|
+
'searchResultsView': function (payload) { /* send payload */ }
|
31
|
+
// ...
|
32
|
+
};
|
33
|
+
});
|
34
|
+
```
|
35
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
---
|
2
|
+
title: Integrate an Inventory Management System
|
3
|
+
excerpt: Procedures for integrating Workarea with an external inventory system of record
|
4
|
+
---
|
5
|
+
|
6
|
+
Integrate an Inventory Management System
|
7
|
+
======================================================================
|
8
|
+
|
9
|
+
Workarea provides an inventory system that satisfies the needs of many retailers.
|
10
|
+
However, some retailers prefer to manage their inventory in another system, usually an enterprise resource planner (ERP).
|
11
|
+
|
12
|
+
In this case, you will need to integrate Workarea with the external system to keep their inventory data in sync, which is the subject of this document.
|
13
|
+
To integrate inventory from an ERP, you must routinely update Workarea's inventory SKUs with data from the authoritative inventory system, specifically the fields `:available` and `:backordered`.
|
14
|
+
Furthermore, you may need to report to the external system any changes that Workarea makes to these fields, which are recorded in inventory transactions.
|
15
|
+
|
16
|
+
This document additionally provides general advice for integrating Workarea with another system (of any type).
|
17
|
+
|
18
|
+
|
19
|
+
Update Inventory SKUs within Workarea
|
20
|
+
----------------------------------------------------------------------
|
21
|
+
|
22
|
+
Within Workarea, each item's inventory is represented by an inventory SKU, which is identified by the item's SKU.
|
23
|
+
( See [Inventory: Inventory SKUs](inventory.html#inventory-skus_2). )
|
24
|
+
Several administrable fields, primarily the integer fields `:available` and `:backordered`, represent the "raw" inventory data tracked by Workarea.
|
25
|
+
( See [Inventory: Administrable Fields & Policies](inventory.html#administrable-fields-amp-policies_3). )
|
26
|
+
|
27
|
+
You must design a strategy for keeping these fields in sync with the corresponding data from the external inventory system.
|
28
|
+
__Maintaining accurate values for these fields is the core of this integration.__
|
29
|
+
Refer to "General Tips for System Integration" below for further advice on this matter.
|
30
|
+
|
31
|
+
|
32
|
+
Report Workarea's Inventory Transactions
|
33
|
+
----------------------------------------------------------------------
|
34
|
+
|
35
|
+
Workarea also makes its own changes to the inventory SKU values `:available` and `:backordered` when shoppers place and cancel orders.
|
36
|
+
( See [Inventory: Purchasing, Capturing & Releasing Inventory](inventory.html#purchasing-capturing-amp-releasing-inventory_14). )
|
37
|
+
You therefore may need to report these changes to the system you are integrating.
|
38
|
+
( This may not be necessary if the external system manages these changes, perhaps during fulfillment rather than at the point of sale. )
|
39
|
+
|
40
|
+
Whenever Workarea captures and frees inventory in this manner, it records details of the changes as an `Inventory::Transaction` specific to the order.
|
41
|
+
Each inventory transaction is related to an order via its `:order_id` field.
|
42
|
+
Whenever Workarea performs a capture, rollbak, or restock operation on inventory, its affects are recorded on the inventory transaction document, and its `:updated_at` timestamp is refreshed.
|
43
|
+
Additionally, you can query whether a transaction's inventory has been captured by examining its boolean `:captured` field.
|
44
|
+
|
45
|
+
Inventory transactions are indexed by `:updated_at` and `:captured`, facilitating queries for "captured transactions updated after _date_":
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
# find inventory transactions updated after Midnight
|
49
|
+
|
50
|
+
Workarea::Inventory::Transaction.where(
|
51
|
+
:updated_at.gt => Time.current.beginning_of_day,
|
52
|
+
captured: true
|
53
|
+
)
|
54
|
+
```
|
55
|
+
|
56
|
+
You can use such a query to fetch the transactions that were updated since your last such query, enabling you to prepare ad-hoc reports to send to the partnering system.
|
57
|
+
Each inventory transaction embeds a collection of `Inventory::TransactionItem` documents, one document per corresponding `Order::Item`.
|
58
|
+
Each transaction item has the fields `:sku`, `:available`, and `:backordered`, where `:available` and `:backordered` indicate the number of units captured.
|
59
|
+
You or the ERP can fetch and share this data routinely to keep the external system in sync with Workarea's inventory changes.
|
60
|
+
|
61
|
+
|
62
|
+
General Tips for System Integration
|
63
|
+
----------------------------------------------------------------------
|
64
|
+
|
65
|
+
Until Workarea provides general-purpose documentation for system integration, a brief summary of the process is described here.
|
66
|
+
|
67
|
+
|
68
|
+
### Determine Responsibilities
|
69
|
+
|
70
|
+
An integration involves two systems and two teams, so you must determine who is responsible for what.
|
71
|
+
Work with the partnering team to determine the following:
|
72
|
+
|
73
|
+
* Who is pushing or pulling data?
|
74
|
+
* According to what schedule or in response to what events?
|
75
|
+
* Who is responsible for transforming the data to/from the opposing data format?
|
76
|
+
* When updating, are you updating all the records, or only those that have changed since the last update?
|
77
|
+
* And who is responsible for determining which records have changed since the last update?
|
78
|
+
|
79
|
+
|
80
|
+
### Build the Integration
|
81
|
+
|
82
|
+
Next, build the parts of the integration for which you are responsible.
|
83
|
+
Tools for this within the Workarea system include:
|
84
|
+
|
85
|
+
* [Admin API](https://plugins.workarea.com/plugins/api-admin)
|
86
|
+
* [Callbacks workers](workers.html#callbacks-worker_7)
|
87
|
+
* [Scheduled workers](workers.html#sidekiq-cron-job_5)
|
88
|
+
* [Data file scheduling](https://plugins.workarea.com/plugins/data-file-scheduling)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
---
|
2
|
+
title: Integrating with Other Software
|
3
|
+
excerpt: Overview of a developer's options for integrating Workarea with third-party software.
|
4
|
+
---
|
5
|
+
|
6
|
+
# Integrating with Other Software
|
7
|
+
|
8
|
+
Integrating with other systems is one of the toughest parts of a large-scale ecommerce site build. Whether it's an ESP, a crusty old mainframe system, or a homegrown CRM, Workarea has many options to help. Picking between these depends on the needs, capabilities, and people of the system you're integrating with, so below you'll find the major options outlined.
|
9
|
+
|
10
|
+
## Plugins
|
11
|
+
|
12
|
+
The easiest option for integration is a plugin already built by the Workarea team or the community. A typical install means adding the gem to the project's `Gemfile` and configuring some credentials. You'll want to check the README on the plugin for details.
|
13
|
+
|
14
|
+
To see a list of available open-source integration plugins, check out the Workarea [Github repositories](https://github.com/workarea-commerce). For more info on how plugins work (including how to write your own), see the [plugins overview](plugins-overview.html).
|
15
|
+
|
16
|
+
## API
|
17
|
+
|
18
|
+
The admin API offers the minimum amount of work on the Workarea side for the integration. Through the API, you can get and/or update all the major resources in the Workarea system. This is a great option if you have the cooperation of developers on the other end - they can write calls to the API as needed.
|
19
|
+
|
20
|
+
See the [API overview](api-overview.html) for more info, or jump into the deep end with [the API documentation](https://demo.workarea.com/api/docs).
|
21
|
+
|
22
|
+
## Webhooks
|
23
|
+
|
24
|
+
Webhooks are an option where Workarea will call out to a provided URL with a payload when a particular event (e.g. an order gets placed or a customer account is created) occurs. The payload will contain data related to the event. This is nearer to real-time than the other out-of-the-box options. Like API integration, choosing webhooks is good when you have the cooperation of developers on the other end. Someone will have to setup the desired events/URLs in the admin.
|
25
|
+
|
26
|
+
See the [Webhooks plugin](https://github.com/workarea-commerce/workarea-webhooks) for more info.
|
27
|
+
|
28
|
+
## Scheduled Data Files
|
29
|
+
|
30
|
+
Scheduling data file transfers is a more old-fashioned, but still automated option for integration. Great for overnight batched integrations with older systems that will need to ingest CSV files and the like. An administrator can specify what they want to import or export, how often and when. It supports S3, SFTP, or local file system as data stores.
|
31
|
+
|
32
|
+
See the [Data File Scheduling plugin](https://github.com/workarea-commerce/workarea-data-file-scheduling) for more info.
|
33
|
+
|
34
|
+
## Admin Import/Export
|
35
|
+
|
36
|
+
All the major index pages in the admin (people, orders, products, etc) are available to import and export in multiple formats from the admin interface. The links appear in the workflow bar in the bottom left of those screens. The downside to this option is that everything must be completely manual.
|
37
|
+
|
38
|
+

|
39
|
+
|
40
|
+
## Custom Code
|
41
|
+
|
42
|
+
The most manual, developer-involved option for integration with third party software is to write the code manually. Obviously this the most expensive/time-consuming of the options. The advantage however, is the integration can be built completely bespoke to the merchant's needs.
|
43
|
+
|
44
|
+
|
45
|
+
### Scheduled Workers
|
46
|
+
|
47
|
+
Scheduled workers are good for working in batches, for example exporting orders every hour. Workarea includes a gem for scheduling Sidekiq jobs called [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron). As a super admin, you'll be able to monitor the status of these jobs in the Sidekiq admin at `/admin/sidekiq/cron`.
|
48
|
+
|
49
|
+
See the [Sidekiq Cron Job section](workers.html#sidekiq-cron-job_5) of the [workers article](workers.html).
|
50
|
+
|
51
|
+
### Callbacks Workers
|
52
|
+
|
53
|
+
Another good asynchronous option is callbacks workers. Workarea adds an extension to Sidekiq worker functionality to allow automatically enqueueing Sidekiq workers based on customizable callbacks in models. This is good for doing individual calls to external systems as the events in Workarea happen. For example, when an email signup is created, run a Sidekiq worker to add that email to an ESP.
|
54
|
+
|
55
|
+
See the [Sidekiq Callbacks section](workers.html#sidekiq-callbacks_11) of the [workers article](workers.html).
|
56
|
+
|
57
|
+
### Inline
|
58
|
+
|
59
|
+
This is least preferred option of all for this task, due to its fragility. It puts the stability of Workarea at the mercy of the other system. The basic idea is adding in the calls to the external software inline with the Workarea code. Examples would be putting calls to fraud checks in checkout controllers, or "real-time" inventory calls from product detail pages. The pattern you'll use to do this is called "decoration", you can read more about it in [our decorators article](decoration.html).
|
@@ -0,0 +1,352 @@
|
|
1
|
+
---
|
2
|
+
title: Inventory
|
3
|
+
excerpt: Workarea includes an inventory subsystem providing inventory management and automated merchandising, which developers can extend
|
4
|
+
---
|
5
|
+
|
6
|
+
Inventory
|
7
|
+
======================================================================
|
8
|
+
|
9
|
+
Workarea includes an inventory subsystem providing inventory management and automated merchandising based on inventory levels and policies.
|
10
|
+
This system is fully functional as it is, but developers may need to extend or operate the system to accomplish the following:
|
11
|
+
|
12
|
+
* Integrate Workarea with a retailer's inventory management system
|
13
|
+
* Define and configure inventory policies
|
14
|
+
* Explain to a retailer how the inventory system works, including inventory management and inventory's effects on the shopping experience (for example, you may need to explain how an item's inventory is preventing a product from matching a search)
|
15
|
+
|
16
|
+
To develop these skills, you'll need to know the following:
|
17
|
+
|
18
|
+
* How retailers manage inventory within Workarea
|
19
|
+
* How Workarea protects retailers by not overselling, while also maintaining the quality of the shopping experience for shoppers
|
20
|
+
* How Workarea captures and releases inventory when shoppers place and cancel orders, which maintains inventory integrity
|
21
|
+
|
22
|
+
This document therefore describes the Workarea inventory system, from management to reporting.
|
23
|
+
|
24
|
+
A retailer manages __inventory SKUs__, each of which has __administrable fields__, including a __policy__, from which Workarea derives various __inventory SKU states__.
|
25
|
+
Workarea uses these states to prevent overselling and to communicate availability when presenting searches, categories, recommendations, products, and carts.
|
26
|
+
Finally, when shoppers place and cancel orders, Workarea __purchases__, __captures__, and __releases__ inventory, managing the same inventory fields as retailers.
|
27
|
+
Workarea records these __inventory transactions__ for each order and also provides reports and insights to help a retailer restock inventory effectively.
|
28
|
+
|
29
|
+
|
30
|
+
Inventory Management
|
31
|
+
----------------------------------------------------------------------
|
32
|
+
|
33
|
+
A retailer can manage inventory within Workarea directly or within a separate inventory management system that is integrated with Workarea.
|
34
|
+
( Regarding the latter, see [Integrate an Inventory Management System](integrate-an-inventory-management-system.html). )
|
35
|
+
In either case, the retailer manages inventory via several administrable fields on inventory SKUs.
|
36
|
+
|
37
|
+
|
38
|
+
### Inventory SKUs
|
39
|
+
|
40
|
+
An _inventory SKU_ is a MongoDB-backed model representing the inventory for an item in the retailer's catalog.
|
41
|
+
Each inventory SKU is identified by the item's SKU, a retailer-specific ID that relates the inventory SKU to other models representing the same item within Workarea.
|
42
|
+
( See [Products](products.html) for a more thorough explanation of the models that represent merchandise, and their relationships. )
|
43
|
+
|
44
|
+
Administrators, developers, and automated systems manage inventory by manipulating several administrable fields on each inventory SKU, including the inventory SKU's policy.
|
45
|
+
|
46
|
+
|
47
|
+
### Administrable Fields & Policies
|
48
|
+
|
49
|
+
The following table describes the _administrable fields_ of each inventory SKU:
|
50
|
+
|
51
|
+
| Field | Description |
|
52
|
+
| ----- | ----------- |
|
53
|
+
| `:available` | The integer count of units that are available except when reserved; defaults to `0` |
|
54
|
+
| `:backordered` | The integer count of units that are available when backorder is allowed, except when reserved, defaults to `0` |
|
55
|
+
| `:reserve` | The integer count of units to reserve from the collective pool of `available` and `backordered`; defaults to `0` |
|
56
|
+
| `:backordered_until` | The `Time` at which backordered units are expected to move to available |
|
57
|
+
| `:policy` | A string identifying one of the policies enumerated in `Workarea.config.inventory_policies`; defaults to the first policy in that configurable collection |
|
58
|
+
|
59
|
+
The most important of these fields are the integer values `:available`, `:backordered` and `reserve`, and the `:policy`, which Workarea uses collectively to derive various inventory states, as explained in the following sections.
|
60
|
+
|
61
|
+
|
62
|
+
Presenting Products & Carts
|
63
|
+
----------------------------------------------------------------------
|
64
|
+
|
65
|
+
While the retailer is responsible for setting the inventory values in the above fields, Workarea is responsible for honoring those values throughout the shopping experience.
|
66
|
+
Workarea must prevent overselling to protect the retailer, and must also maintain the user experience for shoppers.
|
67
|
+
To accomplish both goals, Workarea performs automatic merchandising which prevents shoppers from adding unavailable items to their carts, or may hide items from shoppers altogether while inventory is unavailable.
|
68
|
+
This requires determining the displayability and purchasability of each item, based on its inventory.
|
69
|
+
Workarea derives these states from the administrable fields on the inventory SKU.
|
70
|
+
|
71
|
+
|
72
|
+
### Inventory Policies & SKU States
|
73
|
+
|
74
|
+
Introduced above, an _inventory policy_ is a class of object that declares the logic for converting the administrable values of an inventory SKU into _inventory SKU states_.
|
75
|
+
An inventory policy also declares the logic for purchasing a SKU's inventory, which is covered below.
|
76
|
+
|
77
|
+
Workarea includes several inventory policies, and plugins and applications can define and configure their own policies.
|
78
|
+
( For a more in-depth look at policy class definitions and configuration, see [Define & Configure Inventory Policies](define-and-configure-inventory-policies.html). )
|
79
|
+
The following example enumerates the available policies:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
puts Workarea.config.inventory_policies
|
83
|
+
# Workarea::Inventory::Policies::Ignore
|
84
|
+
# Workarea::Inventory::Policies::Standard
|
85
|
+
# Workarea::Inventory::Policies::DisplayableWhenOutOfStock
|
86
|
+
# Workarea::Inventory::Policies::AllowBackorder
|
87
|
+
```
|
88
|
+
|
89
|
+
For each inventory SKU, workarea uses the SKU's policy and other values of its administrable fields to derive the following inventory SKU states:
|
90
|
+
|
91
|
+
| State | Description |
|
92
|
+
| ----- | ----------- |
|
93
|
+
| `available_to_sell` | The computed integer count of available units, derived from `:available`, `:backordered`, and `reserve` by the policy |
|
94
|
+
| `purchasable?(quantity)` | Whether the item is purchasable, determined by comparing the given quantity to `available_to_sell`; quantity defaults to `1` |
|
95
|
+
| `displayable?` | Whether the item is displayable, as determined by the policy |
|
96
|
+
| `backordered?` | Whether the item is backordered, which can be true only when the policy is `'allow_backorder'` |
|
97
|
+
|
98
|
+
The following sections explain each inventory policy and its effects on these inventory SKU states.
|
99
|
+
|
100
|
+
|
101
|
+
#### Standard
|
102
|
+
|
103
|
+
The standard policy allows purchase only from the `:available` units, minus those in `:reserve`.
|
104
|
+
An item is displayable if it is purchasable.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
# create an inventory SKU
|
108
|
+
sku = 'WIZRDRPG-5ED'
|
109
|
+
inventory_sku = Workarea::Inventory::Sku.create(
|
110
|
+
_id: sku,
|
111
|
+
policy: 'standard',
|
112
|
+
available: 0,
|
113
|
+
backordered: 3,
|
114
|
+
reserve: 1
|
115
|
+
)
|
116
|
+
|
117
|
+
# review the administrable values
|
118
|
+
inventory_sku.available
|
119
|
+
# => 0
|
120
|
+
inventory_sku.backordered
|
121
|
+
# => 3
|
122
|
+
inventory_sku.reserve
|
123
|
+
# => 1
|
124
|
+
|
125
|
+
# there are none available to sell, because this policy
|
126
|
+
# does not allow purchase from :backordered
|
127
|
+
inventory_sku.available_to_sell
|
128
|
+
# => 0
|
129
|
+
|
130
|
+
# The item is therefore not purchasable and not displayable
|
131
|
+
inventory_sku.purchasable?
|
132
|
+
# => false
|
133
|
+
inventory_sku.displayable?
|
134
|
+
# => false
|
135
|
+
|
136
|
+
# And it is not considered backordered
|
137
|
+
inventory_sku.backordered?
|
138
|
+
# => false
|
139
|
+
```
|
140
|
+
|
141
|
+
|
142
|
+
#### Allow Backorder
|
143
|
+
|
144
|
+
When backorder is allowed, units from `:backordered` are additionally available for purchase, minus those in `:reserve`.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# change the inventory SKU's policy and re-initialize it
|
148
|
+
# (to clear the memoized policy object)
|
149
|
+
inventory_sku.update_attribute(:policy, 'allow_backorder')
|
150
|
+
inventory_sku = Workarea::Inventory::Sku.find(sku)
|
151
|
+
|
152
|
+
# the administrable values haven't changed
|
153
|
+
inventory_sku.available
|
154
|
+
# => 0
|
155
|
+
inventory_sku.backordered
|
156
|
+
# => 3
|
157
|
+
inventory_sku.reserve
|
158
|
+
# => 1
|
159
|
+
|
160
|
+
# But the item is now considered backordered
|
161
|
+
inventory_sku.backordered?
|
162
|
+
# => true
|
163
|
+
|
164
|
+
# And there are units to sell
|
165
|
+
inventory_sku.available_to_sell
|
166
|
+
# => 2
|
167
|
+
|
168
|
+
# Up to 2 units are purchasable; the 3rd is reserved
|
169
|
+
inventory_sku.purchasable?
|
170
|
+
# => true
|
171
|
+
inventory_sku.purchasable?(2)
|
172
|
+
# => true
|
173
|
+
inventory_sku.purchasable?(3)
|
174
|
+
# => false
|
175
|
+
|
176
|
+
# And the item is displayable
|
177
|
+
inventory_sku.displayable?
|
178
|
+
# => true
|
179
|
+
```
|
180
|
+
|
181
|
+
|
182
|
+
#### Displayable When Out of Stock
|
183
|
+
|
184
|
+
An item that is displayable when out of stock behaves like a standard item, except it remains displayable when not purchasable.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
# Change the policy and re-init the inventory SKU
|
188
|
+
inventory_sku.update_attribute(:policy, 'displayable_when_out_of_stock')
|
189
|
+
inventory_sku = Workarea::Inventory::Sku.find(sku)
|
190
|
+
|
191
|
+
# No changes to the administrable values
|
192
|
+
inventory_sku.available
|
193
|
+
# => 0
|
194
|
+
inventory_sku.backordered
|
195
|
+
# => 3
|
196
|
+
inventory_sku.reserve
|
197
|
+
# => 1
|
198
|
+
|
199
|
+
# This policy does not allow backorder
|
200
|
+
inventory_sku.backordered?
|
201
|
+
# => false
|
202
|
+
|
203
|
+
# So there are therefore none to sell, and
|
204
|
+
# the item is not purchasable
|
205
|
+
inventory_sku.available_to_sell
|
206
|
+
# => 0
|
207
|
+
inventory_sku.purchasable?
|
208
|
+
# => false
|
209
|
+
|
210
|
+
# However, it is displayable
|
211
|
+
inventory_sku.displayable?
|
212
|
+
# => true
|
213
|
+
```
|
214
|
+
|
215
|
+
|
216
|
+
#### Ignore
|
217
|
+
|
218
|
+
Ignoring inventory can be useful for intangible items, such as gift cards, that have effectively infinite inventory.
|
219
|
+
A retailer may also use this policy if they are not concerned with tracking inventory within Workarea.
|
220
|
+
This is the default inventory policy.
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
# Change the policy and re-init the inventory SKU
|
224
|
+
inventory_sku.update_attribute(:policy, 'ignore')
|
225
|
+
inventory_sku = Workarea::Inventory::Sku.find(sku)
|
226
|
+
|
227
|
+
# Administrable values are the same
|
228
|
+
inventory_sku.available
|
229
|
+
# => 0
|
230
|
+
inventory_sku.backordered
|
231
|
+
# => 3
|
232
|
+
inventory_sku.reserve
|
233
|
+
# => 1
|
234
|
+
|
235
|
+
# The item is not backordered
|
236
|
+
inventory_sku.backordered?
|
237
|
+
# => false
|
238
|
+
|
239
|
+
# But there are effectively infinite units available
|
240
|
+
# (This value will not change, even as orders with this item are placed)
|
241
|
+
inventory_sku.available_to_sell
|
242
|
+
# => 99999
|
243
|
+
|
244
|
+
# The item is therefore always purchasable and displayable
|
245
|
+
inventory_sku.purchasable?
|
246
|
+
# => true
|
247
|
+
inventory_sku.displayable?
|
248
|
+
# => true
|
249
|
+
```
|
250
|
+
|
251
|
+
|
252
|
+
### Searches, Categories & Recommendations
|
253
|
+
|
254
|
+
Workarea presents the items of the retailer's catalog as [products](products.html), which are (generally small) collections of items that share a name, description, and some details, while varying on other details (such as color, size, etc).
|
255
|
+
When a product document is indexed into Elasticsearch, it contains inventory information from all the items that make up the product.
|
256
|
+
|
257
|
+
[Storefront search features](storefront-search-features.html), such as searches, categories, and product recommendations, take inventory into account when deciding which products match and how they are sorted in results.
|
258
|
+
The inventory-related display logic can be summarized as follows:
|
259
|
+
|
260
|
+
* To match a search or category, a product must have at least one displayable SKU
|
261
|
+
* To match a query for search-based recommendations, a product must have at least one purchasable SKU
|
262
|
+
* When sorted by relevance (as opposed to a user-defined sort), search and category results sort products with at least one purchasable SKU above those without a purchasable SKU (unless the product is featured; featured products sort to the top)
|
263
|
+
|
264
|
+
Search features essentially re-implement the concepts of displayable and purchasable using inventory fields within product search documents and with queries defined with the Elasticsearch query DSL.
|
265
|
+
__These determinations can therefore be "stale" relative to the current inventory values in MongoDB__.
|
266
|
+
|
267
|
+
A retailer can use inventory policies to determine how products should appear in the results for search-based features.
|
268
|
+
It may be desirable for an item to be included in results even when it is not purchasable, but Workarea will de-prioritize the product within the results.
|
269
|
+
|
270
|
+
The purpose of these presentation rules is to prevent shoppers from adding to their cart items that are not purchasable, which would create a poor user experience for the shopper.
|
271
|
+
|
272
|
+
|
273
|
+
### Products & Carts
|
274
|
+
|
275
|
+
While searching and browsing products, a shopper will often select a specific product to view in detail.
|
276
|
+
The product detail page (PDP), like the search features, reflects the inventory of the items that make up the product.
|
277
|
+
|
278
|
+
A PDP presents product options that the shopper selects to narrow the product to a specific item to be added to the shopper's cart.
|
279
|
+
The product options are derived from the details of the product's displayable SKUs, hence, retailers can use inventory policies to determine which options should display.
|
280
|
+
For example, an item with only backordered inventory is considered displayable when the SKU's policy is `AllowBackorder`, but not when the policy is `Standard`.
|
281
|
+
|
282
|
+
Furthermore, after narrowing to a specific item, the shopper can add the item to the cart only if it is purchasable.
|
283
|
+
To continue the previous example, an item with only backordered inventory can be added to the cart only if its policy is `AllowBackorder` or `Ignore`.
|
284
|
+
|
285
|
+
As with the search features, these rules on the PDP are intended to keep non-purchasable items out of shoppers carts.
|
286
|
+
However, after a shopper adds an item to their cart, it can become non-purchasable if other shoppers purchase the remaining inventory first (or inventory changes due to inventory management).
|
287
|
+
Workarea therefore checks inventory on most cart and checkout requests to ensure the items in the cart are still purchasable.
|
288
|
+
If items become non-purchasable, Workarea removes them from the cart and notifies the shopper.
|
289
|
+
|
290
|
+
|
291
|
+
### Inventory Status Messages
|
292
|
+
|
293
|
+
To more directly communicate an item's availability to shoppers, Workarea displays _inventory status messages_ on the PDP and in the cart.
|
294
|
+
The messages are per-item, so on the PDP a shopper must first narrow the product to a specific item before being shown the inventory status.
|
295
|
+
|
296
|
+
The inventory status shown is one of the following:
|
297
|
+
|
298
|
+
* In Stock
|
299
|
+
* _Number_ Left
|
300
|
+
* Ships on _Date_
|
301
|
+
* Backordered
|
302
|
+
* Out of Stock
|
303
|
+
|
304
|
+
These messages are for display only, and their logic is therefore encapsulated in a [view model](view-models.html): `Storefront::InventoryStatusViewModel`.
|
305
|
+
Review the implementation of that view model in your Workarea version to see the logic for each status.
|
306
|
+
|
307
|
+
|
308
|
+
Placing & Canceling Orders
|
309
|
+
----------------------------------------------------------------------
|
310
|
+
|
311
|
+
You've seen above how Workarea prevents the sale of non-purchasable merchandise.
|
312
|
+
However, as shoppers place orders, Workarea must maintain accurate inventory levels.
|
313
|
+
Workarea uses inventory transactions to purchase and release inventory as users place and cancel orders.
|
314
|
+
Furthermore, Workarea exposes these inventory changes in the Admin through reports and insights.
|
315
|
+
|
316
|
+
|
317
|
+
### Purchasing, Capturing & Releasing Inventory
|
318
|
+
|
319
|
+
To maintain accurate inventory within its boundaries, Workarea must _purchase_ the inventory for an order, according to the inventory policy of each SKU.
|
320
|
+
|
321
|
+
Regardless of policy, the value of `:purchased` on the inventory SKU is incremented by the quantity purchased.
|
322
|
+
This value tracks the number of units purchased since the creation of the inventory SKU.
|
323
|
+
Additionally, the current computed value from `#available_to_sell` is persisted to the field `:sellable`, which is used for presenting a low inventory report.
|
324
|
+
|
325
|
+
Depending on policy, units are _captured_ from `:available` and `:backordered`, as described in the following table:
|
326
|
+
|
327
|
+
| Policy | Capture Logic |
|
328
|
+
| ------ | ------------- |
|
329
|
+
| `'standard'` | Purchased quantity is decremented from `:available` |
|
330
|
+
| `'displayable_when_out_of_stock'` | Same as `'standard'`, from which it inherits |
|
331
|
+
| `'allow_backorder'` | Purchased quantity is decremented first from `:available` (until exhausted) and then from `:backordered` |
|
332
|
+
| `'ignore'` | Nothing is captured |
|
333
|
+
|
334
|
+
If a shopper later cancels the order, Workarea must _release_ the inventory, which is the reverse of a capture and relies on the record of the purchase stored in the inventory transaction.
|
335
|
+
|
336
|
+
|
337
|
+
### Inventory Transactions
|
338
|
+
|
339
|
+
When an order is placed, the details of the inventory captured are recorded in an _inventory transaction_, a separate document (an `Inventory::Transaction`) which embeds an inventory transaction item for each corresponding order item.
|
340
|
+
Inventory transactions are used to manage the capturing of inventory and to provide a permanent record of what was captured.
|
341
|
+
They are also used in the event of a cancellation to free the appropriate amount of inventory.
|
342
|
+
|
343
|
+
( Inventory transactions are also covered in [Integrate an Inventory Management System](integrate-an-inventory-management-system.html). )
|
344
|
+
|
345
|
+
|
346
|
+
### Reports & Insights
|
347
|
+
|
348
|
+
Because Workarea is modifying inventory counts, it must provide a means for retailers to stay informed of current inventory levels.
|
349
|
+
In addition to the inventory SKU administration screens, Workarea provides two reports directly relevant to those responsible for restocking inventory: "Low Inventory" and "Sales by Product".
|
350
|
+
A retailer can view and export these reports in the Admin.
|
351
|
+
Insights based on these reports also appear within several Admin dashboards.
|
352
|
+
Relying on these insights, retailers can effectively manage inventory levels, completing the inventory cycle explained in this document.
|