PhoenixKitEcommerce.Catalogue.ShopStatusColumn (PhoenixKitEcommerce v0.5.11)

Copy Markdown View Source

The catalogue admin's "Shop status" extension column — surfaces data["ecommerce"]["shop_status"] next to the catalogue's OWN status on the item/category tables.

The owner's complaint: the catalogue's status and the shop's shop_status are two independent signals — an item can be a live catalogue entry that is deliberately not for sale — and only the catalogue's own status showed on screen, so an item could be invisible on the storefront (or, worse, reachable when it shouldn't be — see below) for a reason the admin screen never surfaced. This column does NOT synchronize the two (that would destroy the distinction the owner wants to keep); it shows both, side by side, and never warns — see "No warnings" below for why there is no combination left that is an actual hazard.

Why item and category are two different rules (item_columns/0

vs. category_columns/0 return DIFFERENT column definitions)

Items and categories share neither their shop_status value domain nor their storefront-visibility rule:

  • Item shop_statusdraft / active / archived (PhoenixKitEcommerce.Catalogue.ItemCommerce). Listing visibility (ProductSource.Catalogue.Query.active_visibility/1) requires item.status == "active" AND COALESCE(shop_status, 'active') == "active" — an absent shop_status defaults to whatever item.status already says (View.product_status/2's exact fallback), so it never disagrees with the catalogue by itself.
  • Category shop_statusactive / unlisted / hidden (CategoryCommerce). Only hidden removes a category's items from listings (Query.exclude_hidden_categories/2); unlisted only hides the category's own nav entry — its page and items stay directly reachable. An absent shop_status defaults UNCONDITIONALLY to "active" (View.category_view/2: Map.get(ecommerce, "shop_status") || "active" — no fallback to c.status at all).

No warnings — the reachability leak is closed on both sides

An earlier version of this column warned on the one combination that was a real hazard: the shop reporting something as visible while the catalogue had retired or soft-deleted it, so that it was excluded from every listing, count and facet (ProductSource.Catalogue.Query.active_visibility/1 unconditionally requires item.status == "active" / c.status != "deleted") yet still reachable by direct link, because the single-record pages resolved the status from shop_status alone.

That leak is now closed at the source for both record types, so there is nothing left to warn about:

  • Items — View.product_status/2 checks item.status FIRST and forces "archived" on any non-active catalogue status regardless of shop_status (phoenix_kit_ecommerce PR #53), so CatalogProduct.do_mount/3 (which redirects on any resolved status != "active") cannot be fooled by a stale explicit shop_status: "active".
  • Categories — View.category_status/2 forces "hidden" for a catalogue-deleted category no matter what shop_status says (commit af9308b; catalog_category_catalogue_status_test.exs proves the page redirects), so CatalogCategory.do_mount/3's block-list gate (redirect only on literal "hidden") is reached with the forced value, never the stale one.

What remains is a catalogue/shop DISAGREEMENT (a discontinued item with shop_status: "active"; a deleted category with "unlisted") — display-only information the admin may want to see, but not a hazard, and every other disagreement (catalogue active while the shop says draft/archived/hidden/unlisted) is simply how the owner deliberately keeps something out of the shop while it stays a live catalogue entry. All of them render with no warning. An absent shop_status is shown as the value it effectively resolves to (per the fallbacks above), marked "(default)" rather than as an alarming "Unknown" — it is not a misconfiguration, just a namespace the Shop section has never written.

Reached only through PhoenixKitEcommerce.Catalogue.Extension's item_columns/0/category_columns/0 — see that module's moduledoc for the discovery contract, and PhoenixKitCatalogue.Extension's typedoc (in the optional phoenix_kit_catalogue dependency) for the exact %{id:, label:, render:} shape this returns. Written duck-typed on purpose: nothing here references a PhoenixKitCatalogue module, so it compiles and behaves identically whether or not that dependency, or the extension-column slot it implements, is present at all.

Badge colours

Core's PhoenixKitWeb.Components.Core.Badge.status_badge/1 has no case for unlisted/hidden/an unrecognized value — all three fall through to the same grey badge-ghost, which would render three semantically different category shop-statuses identically. Rather than edit core, this module picks its own explicit badge class per status (see item_shop_badge/1, category_shop_badge/1, catalogue_badge/1) instead of delegating to status_badge/1.

Summary

Functions

The category_columns/0 entry — see this module's moduledoc.

The item_columns/0 entry — see this module's moduledoc.

Functions

category_columns()

@spec category_columns() :: [map()]

The category_columns/0 entry — see this module's moduledoc.

item_columns()

@spec item_columns() :: [map()]

The item_columns/0 entry — see this module's moduledoc.