Copies of items and categories — the "Duplicate" bulk action.
An item copy is the row plus everything the item form edits alongside
it: multilang data (translations, custom fields, featured-image
pointer), attribute-set attachments, the attribute-group assignment,
the CURRENT supplier rows, catalogue rules, and its files folder. Files
are not re-uploaded: the copy gets its own Storage folder with a
FolderLink to each of the source's files, so removing one from the
copy never touches the original. Supplier rows get a FRESH comment
thread — a discount promised on the original stays on the original.
Comments and activity history are not copied.
A category copy is the category row (same treatment) plus its whole subtree: every active child category and every non-trashed item, each keeping its own name and position. Only the top-level copy is renamed ("Alpha (copy)") and slotted right after its source.
Everything for one copy runs in one transaction; the bulk functions run one transaction per source so a refused row does not undo the others, and emit ONE batch event per touched catalogue afterwards.
Public surface is re-exported from PhoenixKitCatalogue.Catalogue.
Summary
Functions
Copies several categories (each with its subtree); one batch event per catalogue.
Copies several items; one transaction each, one :item batch event per
catalogue. Pass catalogue_uuid: to refuse items outside that catalogue
(:wrong_catalogue_scope) — the uuids are client-captured.
Copies one category with its subtree. Options as duplicate_item/2
(:parent_uuid instead of :category_uuid). Returns the new category and
how many descendant categories and items came along.
Copies one item. Options
Types
@type bulk_result() :: {:ok, %{created: non_neg_integer(), errors: [{Ecto.UUID.t(), term()}]}}
Functions
@spec bulk_duplicate_categories( [Ecto.UUID.t()], keyword() ) :: bulk_result()
Copies several categories (each with its subtree); one batch event per catalogue.
@spec bulk_duplicate_items( [Ecto.UUID.t()], keyword() ) :: bulk_result()
Copies several items; one transaction each, one :item batch event per
catalogue. Pass catalogue_uuid: to refuse items outside that catalogue
(:wrong_catalogue_scope) — the uuids are client-captured.
@spec duplicate_category( PhoenixKitCatalogue.Schemas.Category.t(), keyword() ) :: {:ok, %{ category: PhoenixKitCatalogue.Schemas.Category.t(), categories: non_neg_integer(), items: non_neg_integer() }} | {:error, term()}
Copies one category with its subtree. Options as duplicate_item/2
(:parent_uuid instead of :category_uuid). Returns the new category and
how many descendant categories and items came along.
@spec duplicate_item( PhoenixKitCatalogue.Schemas.Item.t(), keyword() ) :: {:ok, PhoenixKitCatalogue.Schemas.Item.t()} | {:error, term()}
Copies one item. Options:
:category_uuid— put the copy in this category (nil= uncategorized) instead of the source's; the catalogue follows the category.:suffix— append " (copy)" to the name (defaulttrue).:keep_position— keep the source's position number verbatim instead of slotting the copy right after the source (defaultfalse; used for subtree copies where the whole sibling set moves together).:actor_uuid,:mode,:broadcast— as elsewhere in the context.