# `PhoenixKitCatalogue.Catalogue.Rules`
[🔗](https://github.com/BeamLabEU/phoenix_kit_catalogue/blob/0.1.14/lib/phoenix_kit_catalogue/catalogue/rules.ex#L1)

Smart-catalogue rules — one row per `(item, referenced_catalogue)` pair.

Items in a smart catalogue (`kind: "smart"`) reference other catalogues
with a value + unit. The rule row stores the user's intent; consumers
evaluate the math, and `CatalogueRule.effective/2` resolves null
`value` / `unit` to the parent item's `default_value` / `default_unit`.

Provides both the bulk replace-all flow (`put_catalogue_rules/3`,
preferred when editing the full set in a form) and surgical single-rule
CRUD (`create_*` / `update_*` / `delete_*`) for CLI / external use.

Public surface is re-exported from `PhoenixKitCatalogue.Catalogue`.

# `catalogue_reference_count`

```elixir
@spec catalogue_reference_count(Ecto.UUID.t()) :: non_neg_integer()
```

Returns the count of rules referencing a given catalogue (non-deleted
items only). Cheaper than `list_items_referencing_catalogue/1` when
you just need a badge number.

# `catalogue_rule_map`

```elixir
@spec catalogue_rule_map(PhoenixKitCatalogue.Schemas.Item.t() | Ecto.UUID.t()) :: %{
  required(Ecto.UUID.t()) =&gt; PhoenixKitCatalogue.Schemas.CatalogueRule.t()
}
```

Returns the rules for an item as `%{referenced_catalogue_uuid => rule}`.

Convenient for picker UIs that render every available catalogue row
and need O(1) lookup for "is this one checked?". Preloads the
referenced catalogue on each rule.

# `change_catalogue_rule`

```elixir
@spec change_catalogue_rule(PhoenixKitCatalogue.Schemas.CatalogueRule.t(), map()) ::
  Ecto.Changeset.t(PhoenixKitCatalogue.Schemas.CatalogueRule.t())
```

Returns a changeset for tracking a single rule's changes.

# `create_catalogue_rule`

```elixir
@spec create_catalogue_rule(
  map(),
  keyword()
) ::
  {:ok, PhoenixKitCatalogue.Schemas.CatalogueRule.t()}
  | {:error, Ecto.Changeset.t(PhoenixKitCatalogue.Schemas.CatalogueRule.t())}
```

Inserts a single rule. Prefer `put_catalogue_rules/3` for managing an
item's full set of rules; this function exists for surgical edits.

# `delete_catalogue_rule`

```elixir
@spec delete_catalogue_rule(
  PhoenixKitCatalogue.Schemas.CatalogueRule.t(),
  keyword()
) ::
  {:ok, PhoenixKitCatalogue.Schemas.CatalogueRule.t()}
  | {:error, Ecto.Changeset.t(PhoenixKitCatalogue.Schemas.CatalogueRule.t())}
```

Deletes a single rule.

# `get_catalogue_rule`

```elixir
@spec get_catalogue_rule(Ecto.UUID.t(), Ecto.UUID.t()) ::
  PhoenixKitCatalogue.Schemas.CatalogueRule.t() | nil
```

Fetches a single rule by `{item_uuid, referenced_catalogue_uuid}`.
Returns `nil` if not found. Does not preload the referenced catalogue.

# `list_catalogue_rules`

```elixir
@spec list_catalogue_rules(PhoenixKitCatalogue.Schemas.Item.t() | Ecto.UUID.t()) :: [
  PhoenixKitCatalogue.Schemas.CatalogueRule.t()
]
```

Lists the rules attached to an item, ordered by `position` then by the
referenced catalogue's name. The `:referenced_catalogue` association
is preloaded so UIs can render the catalogue name + status without a
second query.

Smart items are the only ones that should have rules; a standard item
simply returns `[]` unless someone put rules on it manually.

# `list_items_referencing_catalogue`

```elixir
@spec list_items_referencing_catalogue(Ecto.UUID.t()) :: [
  PhoenixKitCatalogue.Schemas.Item.t()
]
```

Lists non-deleted smart items that reference a given catalogue.

Useful for warning-before-delete flows: "This catalogue is referenced
by 3 smart items — deleting it cascades to those rules."

Preloads the parent catalogue so the UI can render "Services / Delivery".

# `put_catalogue_rules`

```elixir
@spec put_catalogue_rules(PhoenixKitCatalogue.Schemas.Item.t(), [map()], keyword()) ::
  {:ok, [PhoenixKitCatalogue.Schemas.CatalogueRule.t()]}
  | {:error, {:duplicate_referenced_catalogue, Ecto.UUID.t() | nil}}
  | {:error, Ecto.Changeset.t(PhoenixKitCatalogue.Schemas.CatalogueRule.t())}
```

Atomic replace-all for an item's rules. See moduledoc for context.

# `update_catalogue_rule`

```elixir
@spec update_catalogue_rule(
  PhoenixKitCatalogue.Schemas.CatalogueRule.t(),
  map(),
  keyword()
) ::
  {:ok, PhoenixKitCatalogue.Schemas.CatalogueRule.t()}
  | {:error, Ecto.Changeset.t(PhoenixKitCatalogue.Schemas.CatalogueRule.t())}
```

Updates a single rule's `value`/`unit`/`position`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
