PhoenixKitEcommerce. ProductSource. Catalogue. Query
(PhoenixKitEcommerce v0.5.0)
Copy Markdown
View Source
Ecto queries over phoenix_kit_catalogue's Item/Category schemas,
scoped to the one catalogue the shop reads (get_config("shop_catalogue"),
default name "decor3dprint", resolved through Catalogue.list_catalogues/0).
Returns raw catalogue structs — PhoenixKitEcommerce.ProductSource.Catalogue
turns them into view-structs via Catalogue.View. Nothing here is called
unless ProductSource.current/0 already picked this adapter, which
requires phoenix_kit_catalogue to be loaded; @compile {:no_warn_undefined, ...} only quietens the compiler's static xref
check for hosts that don't declare the optional dependency.
Summary
Functions
Facet counts for one attribute SET's values (set_slug — the set's
entities blueprint name, with or without the "catalogue_set_"
prefix, same lookup filter_by_metadata/2 uses), scoped to
storefront-visible items (active_visibility/1) in the shop
catalogue.
The uuid of the one catalogue the shop reads, or nil when it can't
be resolved (not yet bootstrapped, or the configured name matches
none). Resolved by name on every call — the shop has one catalogue,
so this is one small SELECT against a handful of rows, not a
per-request bottleneck.
Count of items matching opts (no pagination applied).
Fetches one category by uuid, scoped to the shop catalogue.
Fetches one item by uuid, scoped to the shop catalogue. nil on a miss.
Lists the shop catalogue's categories.
Fetches categories by uuid, scoped to the shop catalogue. Missing uuids dropped.
Lists items matching opts, ordered by position, name.
Fetches items by uuid, order preserved, missing uuids dropped, scoped
to the shop catalogue (same "one catalogue only" contract every other
read in this module enforces) — mirrors
PhoenixKitEcommerce.ProductSource.Legacy.list_products_by_ids/1.
list_items/1 plus the total count before pagination is applied.
Min/max base_price over active items, optionally scoped to a category.
Active-item counts grouped by category_uuid, "active" meaning
item.status == "active" and COALESCE(shop_status, 'active') = 'active' (spec principle 7, same fallback as the listing) — items
with no category are excluded, same as
ProductSource.Legacy.product_counts_by_category/0.
Translated display names for a batch of attribute-set BLUEPRINTS,
keyed by set uuid (AttributeSets.resolve_for_item/2's per-set :uuid
field) — ProductSource.Catalogue swaps a resolved set's :name for
this before handing sets to View.product_view/2 (which is pure and
has no way to read settings["translations"] itself). One
AttributeSets.get_set/2 call per DISTINCT set, never per item — a
product page has a handful of attached sets, and a listing page's many
items still share that same handful, so the count stays small; there
is no batched-by-uuid-list entities read to reach for instead. A set
that can't be resolved (deleted, or gated by get_set/2's own owner
check) is simply absent from the result — callers keep the
untranslated :name already on the resolved set for it.
Translated display name of one attribute set by its FILTER-CONFIG slug
(set_slug — with or without the catalogue_set_ prefix, same lookup
filter_by_metadata/2 uses), nil when the slug doesn't resolve to a
set. The sidebar's attribute_set/metadata_option filter section
reads this — a filter config only ever carries the slug, never the
set's uuid.
Distinct vendor values (from data["ecommerce"]["vendor"]) over
active items, with counts, optionally scoped to a category.
Functions
@spec attribute_set_counts(String.t(), keyword()) :: [ %{slug: String.t(), label: String.t(), count: non_neg_integer()} ]
Facet counts for one attribute SET's values (set_slug — the set's
entities blueprint name, with or without the "catalogue_set_"
prefix, same lookup filter_by_metadata/2 uses), scoped to
storefront-visible items (active_visibility/1) in the shop
catalogue.
Options: :category_uuid (scope to one category), :exclude_hidden_categories
(drop items whose category's shop_status is "hidden"), :language
(prefer data[language]["_title"] over the value's bare title —
the picker/sidebar's fuller per-language resolution is Block 5's
remaining work; this covers the plain value label).
A value with no published EntityData row for the requested slug
never appears — draft/archived values (Block 5's resolver creates
unknown Shopify strings as draft) are excluded from storefront
facets by construction, not by a separate filter.
Ordered by the value's position, then its resolved label.
@spec catalogue_uuid() :: Ecto.UUID.t() | nil
The uuid of the one catalogue the shop reads, or nil when it can't
be resolved (not yet bootstrapped, or the configured name matches
none). Resolved by name on every call — the shop has one catalogue,
so this is one small SELECT against a handful of rows, not a
per-request bottleneck.
@spec count_items(keyword()) :: non_neg_integer()
Count of items matching opts (no pagination applied).
@spec get_category(String.t()) :: PhoenixKitCatalogue.Schemas.Category.t() | nil
Fetches one category by uuid, scoped to the shop catalogue.
@spec get_item(String.t()) :: PhoenixKitCatalogue.Schemas.Item.t() | nil
Fetches one item by uuid, scoped to the shop catalogue. nil on a miss.
@spec list_categories(keyword()) :: [PhoenixKitCatalogue.Schemas.Category.t()]
Lists the shop catalogue's categories.
@spec list_categories_by_uuids([String.t()]) :: [ PhoenixKitCatalogue.Schemas.Category.t() ]
Fetches categories by uuid, scoped to the shop catalogue. Missing uuids dropped.
@spec list_items(keyword()) :: [PhoenixKitCatalogue.Schemas.Item.t()]
Lists items matching opts, ordered by position, name.
@spec list_items_by_uuids([Ecto.UUID.t()]) :: [PhoenixKitCatalogue.Schemas.Item.t()]
Fetches items by uuid, order preserved, missing uuids dropped, scoped
to the shop catalogue (same "one catalogue only" contract every other
read in this module enforces) — mirrors
PhoenixKitEcommerce.ProductSource.Legacy.list_products_by_ids/1.
@spec list_items_with_count(keyword()) :: {[PhoenixKitCatalogue.Schemas.Item.t()], non_neg_integer()}
list_items/1 plus the total count before pagination is applied.
Min/max base_price over active items, optionally scoped to a category.
@spec product_counts_by_category() :: %{required(String.t()) => non_neg_integer()}
Active-item counts grouped by category_uuid, "active" meaning
item.status == "active" and COALESCE(shop_status, 'active') = 'active' (spec principle 7, same fallback as the listing) — items
with no category are excluded, same as
ProductSource.Legacy.product_counts_by_category/0.
@spec set_display_names([Ecto.UUID.t()], String.t()) :: %{ required(Ecto.UUID.t()) => String.t() }
Translated display names for a batch of attribute-set BLUEPRINTS,
keyed by set uuid (AttributeSets.resolve_for_item/2's per-set :uuid
field) — ProductSource.Catalogue swaps a resolved set's :name for
this before handing sets to View.product_view/2 (which is pure and
has no way to read settings["translations"] itself). One
AttributeSets.get_set/2 call per DISTINCT set, never per item — a
product page has a handful of attached sets, and a listing page's many
items still share that same handful, so the count stays small; there
is no batched-by-uuid-list entities read to reach for instead. A set
that can't be resolved (deleted, or gated by get_set/2's own owner
check) is simply absent from the result — callers keep the
untranslated :name already on the resolved set for it.
Translated display name of one attribute set by its FILTER-CONFIG slug
(set_slug — with or without the catalogue_set_ prefix, same lookup
filter_by_metadata/2 uses), nil when the slug doesn't resolve to a
set. The sidebar's attribute_set/metadata_option filter section
reads this — a filter config only ever carries the slug, never the
set's uuid.
@spec vendor_counts(keyword()) :: [%{value: String.t(), count: non_neg_integer()}]
Distinct vendor values (from data["ecommerce"]["vendor"]) over
active items, with counts, optionally scoped to a category.