Skip to content

Add to Cart stays enabled on an out-of-stock variant after viewing an in-stock one #2738

Description

@tvlgiao

Add to Cart stays enabled on an out-of-stock variant after viewing an in-stock one

Affects: Cornerstone 6.21.0 and current master · assets/js/theme/common/product-details-base.js

What happens

Pick a variant that is in stock, then switch to one that is out of stock. Add to Cart stays enabled, the sold-out alert stays hidden, and the wallet buttons stay visible — the shopper can add the out-of-stock variant to the cart. Going straight to the out-of-stock variant does not reproduce it, but most storefronts preselect an in-stock option on load.

Verified by running 6.21.0 with stencil start against a live store.

Cause

BigCommerce reports every stock key as null for an out-of-stock variant:

// size S — in stock
{ "instock": true,  "available_to_sell": 1240 }
// size 5XL — out of stock
{ "instock": false, "purchasable": true, "available_to_sell": null, "stock": null }

updateBackorderContext() only writes when the value is a number, so 1240 survives the switch:

if (typeof data.available_to_sell === 'number') {
    this.context.availableToSell = data.available_to_sell;
}

updateDefaultAttributesForOOS() then falls back to that stale number and treats it as the new selection's:

const dataAvailableToSell = typeof data.available_to_sell === 'number'
    ? data.available_to_sell
    : parseInt(this.context.availableToSell, 10) || 0;
const canSell = data.instock || dataAvailableToSell > 0;

Visible proof: after the switch, a large quantity on the out-of-stock variant reports The maximum purchasable quantity is 1240 — the previous variant's stock. updateWalletButtonsView() repeats the same expression.

Fix

Clear the figure when the key is present but not a number, rather than keeping the previous one:

if ('available_to_sell' in data) {
    this.context.availableToSell = typeof data.available_to_sell === 'number'
        ? data.available_to_sell
        : undefined;
}

Same for available_on_hand / stock and available_for_backorder. The verdict then falls to instock / purchasable, which the platform answers for every selection — a backorderable selection with zero on hand still comes back instock: true, so nothing sellable loses its button. Treating null as 0 also stops the symptom but conflates "no figure" with "none left"; restoring the page-level figure reintroduces the bug whenever that figure is positive.

Worth doing at the same time: read unlimited_backorder off the response instead of the context, so a flag left by the previous selection cannot decide the current one.

Second, smaller defect

templates/components/products/product-view.html hides the sold-out alert only while available_to_sell is above zero. A product with an infinite backorder limit reports available_to_sell: 0 (its on-hand count), so the page renders "Sold Out" above a live Add to Cart button. A product with options gets corrected by the next option-change response; one without options never does.

{{#unless product.out_of_stock}} style="display:none"
{{else}}{{#or product.available_to_sell product.unlimited_backorder}} style="display:none"{{/or}}{{/unless}}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions