The Catalog context.
Summary
Functions
Apply automatic filters based on user role and permissions. Returns modified filters map with role-based restrictions applied.
Approve a collection (change status from 'pending' to 'published'). Note: requires reviewed_at, reviewed_by_id, review_notes fields in collections table.
Approves a transfer request and executes the location transfer.
Checks if a barcode prefix already exists in any collection's ID.
Batch approve multiple collections. Returns a tuple with {success_count, failed_count, errors}.
Batch reject multiple collections. Returns a tuple with {success_count, failed_count, errors}.
Cancels a transfer request (by requester).
Returns an %Ecto.Changeset{} for tracking collection changes.
Returns an %Ecto.Changeset{} for tracking collection_field changes.
Returns an %Ecto.Changeset{} for tracking item changes.
Returns an %Ecto.Changeset{} for tracking item_field_value changes.
Returns an %Ecto.Changeset{} for tracking transfer_request changes.
Count pending collections.
Create attachment for a given entity using the new storage system
Create multiple attachments for an entity
Creates a collection.
Creates a collection_field.
Creates a item.
Creates a item_field_value.
Creates a transfer_request.
Delete attachment and its file using the storage system
Deletes a collection.
Deletes a collection_field.
Deletes a item.
Deletes a item_field_value.
Deletes a transfer_request.
Denies a transfer request.
Find item by barcode scan. Supports both full item_code and shortened barcode format.
Get one attachments based on the id
Get attachment statistics for an entity
Gets a single collection.
Gets a single collection_field.
Get the full path/breadcrumb for a collection.
Get review notes for a collection from collection logs. Returns the most recent review notes if available.
Gets all collection IDs that have a matching barcode prefix.
Get collections by their IDs for batch operations. Filters to only include collections that are in pending or draft status.
Get file path for serving
Gets a single item.
Get a single item based on the item_code passed. Returns nil if not found.
Get a single item based on the item_code passed.
Get an item by item_code, barcode, or legacy_item_code.
Gets a single item_field_value.
Get primary attachment for an entity
Get status counts for a user's submitted collections.
Gets a single transfer_request.
Check if a user is an admin. Admins can see all collections without restrictions.
Get all attachments in the system (for asset vault)
Get all attachments for an entity
Get attachments filtered by file type
Get child collections for a given parent collection.
Returns the list of collection_fields.
Returns the list of collections.
List collections with automatic role-based filtering. This function applies filters based on the user's role and permissions
Return the list of collections for pagination with comprehensive filtering.
Get collections organized in a hierarchical tree structure. Now with pagination to prevent loading too many records at once.
Returns the list of item_field_values.
Returns the list of items.
List items with pagination, search, and filters.
Get list of collections with status 'pending' for review.
Get paginated list of pending collections for review.
Get pending transfer requests for a specific node (target node).
Get collections suitable for being parents (excludes the given collection itself and its descendants).
Get root collections (collections without parents).
Get paginated list of collections submitted by a specific user.
Get transfer request history for an item.
Returns the list of transfer_requests with optional filtering.
Load the polymorphic attachable entity (collection or item) for an attachment
Reject a collection (change status from 'pending' to 'draft'). Note: requires reviewed_at, reviewed_by_id, review_notes fields in collections table.
Remove and nilify the thumbnail of an existing collection.
Reorder attachments for an entity
Reviews a transfer request (approve or deny).
Search attachments by filename or description
Search collections across all nodes without scoping. This is used by the collection search workflow to help librarians find existing collections regardless of location.
Search for potential parent collections by title. Returns limited results for performance.
Set attachment as primary (unsets other primary attachments for the same entity)
Update attachment
Updates a collection.
Updates a collection_field.
Updates a item.
Updates a item_field_value.
Updates a transfer_request.
Functions
Apply automatic filters based on user role and permissions. Returns modified filters map with role-based restrictions applied.
Staff members are automatically filtered to:
- Their assigned node (location)
- Their role-specific GLAM type:
- Librarians → Library collections only
- Archivists → Archive collections only
- Gallery Curators → Gallery collections only
- Museum Curators → Museum collections only
Examples
iex> apply_role_based_filters(librarian_user, %{})
%{node_id: 5, glam_type: "Library"} # librarian at node 5
iex> apply_role_based_filters(admin_user, %{})
%{} # no additional filters for admin
Approve a collection (change status from 'pending' to 'published'). Note: requires reviewed_at, reviewed_by_id, review_notes fields in collections table.
Examples
iex> approve_collection(collection, reviewer_user, "Looks good")
{:ok, %Collection{status: "published"}}
Approves a transfer request and executes the location transfer.
Checks if a barcode prefix already exists in any collection's ID.
The barcode prefix is the last 12 characters of a UUID (the final block). This is used to ensure unique barcode generation for items.
Examples
iex> barcode_prefix_exists("90373dfcd91a")
true
iex> barcode_prefix_exists("nonexistent00")
falseParameters
- prefix: The 12-character barcode prefix to check
- exclude_id: Optional collection ID to exclude from the check (for updates)
Returns
- true if the prefix exists in another collection
- false if the prefix is unique
Batch approve multiple collections. Returns a tuple with {success_count, failed_count, errors}.
Examples
iex> batch_approve_collections([%Collection{}, ...], reviewer_user, "Notes")
{2, 0, []}
iex> batch_approve_collections([invalid_collection], reviewer_user, "Notes")
{0, 1, [%{id: "...", title: "...", error: :invalid_status}]}
Batch reject multiple collections. Returns a tuple with {success_count, failed_count, errors}.
Examples
iex> batch_reject_collections([%Collection{}, ...], reviewer_user, "Reason")
{2, 0, []}
iex> batch_reject_collections([invalid_collection], reviewer_user, "Reason")
{0, 1, [%{id: "...", title: "...", error: :invalid_status}]}
Cancels a transfer request (by requester).
Returns an %Ecto.Changeset{} for tracking collection changes.
Examples
iex> change_collection(collection)
%Ecto.Changeset{data: %Collection{}}
Returns an %Ecto.Changeset{} for tracking collection_field changes.
Examples
iex> change_collection_field(collection_field)
%Ecto.Changeset{data: %CollectionField{}}
Returns an %Ecto.Changeset{} for tracking item changes.
Examples
iex> change_item(item)
%Ecto.Changeset{data: %Item{}}
Returns an %Ecto.Changeset{} for tracking item_field_value changes.
Examples
iex> change_item_field_value(item_field_value)
%Ecto.Changeset{data: %ItemFieldValue{}}
Returns an %Ecto.Changeset{} for tracking transfer_request changes.
Count pending collections.
Examples
iex> count_pending_collections()
5
Create attachment for a given entity using the new storage system
Supports both legacy format (%{upload: upload, description: description}) and new format (%{file_url: file_url, filename: filename, content_type: content_type, description: description})
Create multiple attachments for an entity
Creates a collection.
Examples
iex> create_collection(%{field: value})
{:ok, %Collection{}}
iex> create_collection(%{field: bad_value})
{:error, %Ecto.Changeset{}}
Creates a collection_field.
Examples
iex> create_collection_field(%{field: value})
{:ok, %CollectionField{}}
iex> create_collection_field(%{field: bad_value})
{:error, %Ecto.Changeset{}}
Creates a item.
Examples
iex> create_item(%{field: value})
{:ok, %Item{}}
iex> create_item(%{field: bad_value})
{:error, %Ecto.Changeset{}}
Creates a item_field_value.
Examples
iex> create_item_field_value(%{field: value})
{:ok, %ItemFieldValue{}}
iex> create_item_field_value(%{field: bad_value})
{:error, %Ecto.Changeset{}}
Creates a transfer_request.
Delete attachment and its file using the storage system
Deletes a collection.
Examples
iex> delete_collection(collection)
{:ok, %Collection{}}
iex> delete_collection(collection)
{:error, %Ecto.Changeset{}}
Deletes a collection_field.
Examples
iex> delete_collection_field(collection_field)
{:ok, %CollectionField{}}
iex> delete_collection_field(collection_field)
{:error, %Ecto.Changeset{}}
Deletes a item.
Examples
iex> delete_item(item)
{:ok, %Item{}}
iex> delete_item(item)
{:error, %Ecto.Changeset{}}
Deletes a item_field_value.
Examples
iex> delete_item_field_value(item_field_value)
{:ok, %ItemFieldValue{}}
iex> delete_item_field_value(item_field_value)
{:error, %Ecto.Changeset{}}
Deletes a transfer_request.
Denies a transfer request.
Find item by barcode scan. Supports both full item_code and shortened barcode format.
Examples
iex> find_item_by_barcode("c47e6d008b3a001")
%Item{}
iex> find_item_by_barcode("kandaga-book-9c195395-d002-4c2a-8bfb-c47e6d008b3a-1761276668-001")
%Item{}
Get one attachments based on the id
Get attachment statistics for an entity
Gets a single collection.
Raises Ecto.NoResultsError if the Collection does not exist.
Examples
iex> get_collection!(123)
%Collection{}
iex> get_collection!(456)
** (Ecto.NoResultsError)
Gets a single collection_field.
Raises Ecto.NoResultsError if the Collection field does not exist.
Examples
iex> get_collection_field!(123)
%CollectionField{}
iex> get_collection_field!(456)
** (Ecto.NoResultsError)
Get the full path/breadcrumb for a collection.
Examples
iex> get_collection_path(collection)
[%Collection{title: "Harry Potter Series"}, %Collection{title: "Harry Potter 1"}]
Get review notes for a collection from collection logs. Returns the most recent review notes if available.
Examples
iex> get_collection_review_notes(collection_id)
"Looks good, approved for publication"
iex> get_collection_review_notes(collection_id)
nil
Gets all collection IDs that have a matching barcode prefix.
This is useful for debugging and finding collisions.
Examples
iex> get_collections_by_barcode_prefix("90373dfcd91a")
[%Collection{id: "b371e6aa-3fb1-48cf-8439-90373dfcd91a"}, ...]
Get collections by their IDs for batch operations. Filters to only include collections that are in pending or draft status.
Examples
iex> get_collections_for_review(["id1", "id2"])
[%Collection{status: "pending"}, %Collection{status: "draft"}]
Get file path for serving
Gets a single item.
Raises Ecto.NoResultsError if the Item does not exist.
Examples
iex> get_item!(123)
%Item{}
iex> get_item!(456)
** (Ecto.NoResultsError)
Get a single item based on the item_code passed. Returns nil if not found.
Get a single item based on the item_code passed.
Get an item by item_code, barcode, or legacy_item_code.
This function searches across multiple identifier fields to support legacy items and barcode scanning.
Examples
iex> get_item_by_code_or_barcode("ABC123")
%Item{}
iex> get_item_by_code_or_barcode("invalid")
nil
Gets a single item_field_value.
Raises Ecto.NoResultsError if the Item field value does not exist.
Examples
iex> get_item_field_value!(123)
%ItemFieldValue{}
iex> get_item_field_value!(456)
** (Ecto.NoResultsError)
Get primary attachment for an entity
Get status counts for a user's submitted collections.
Returns a map with counts for each status.
Examples
iex> get_submitted_collections_status_counts(user)
%{all: 12, pending: 3, draft: 2, published: 7}
Gets a single transfer_request.
Check if a user is an admin. Admins can see all collections without restrictions.
Get all attachments in the system (for asset vault)
Options
file_type: Filter by file type. For "image", filters to common image formats (jpeg, png, webp)
Get all attachments for an entity
Get attachments filtered by file type
Get child collections for a given parent collection.
Examples
iex> list_children_collections(parent_id)
[%Collection{}, ...]
Returns the list of collection_fields.
Examples
iex> list_collection_fields()
[%CollectionField{}, ...]
Returns the list of collections.
Examples
iex> list_collections()
[%Collection{}, ...]
List collections with automatic role-based filtering. This function applies filters based on the user's role and permissions:
- Staff/Librarians: Filter by their assigned node automatically
- Admins: See all collections
- Users with specific collection permissions: See only permitted collections
Examples
iex> list_collections_for_user(user, page, per_page, search, filters)
{[%Collection{}, ...], total_pages}
Return the list of collections for pagination with comprehensive filtering.
Examples
iex> list_collections_paginated(page, per_page, search, filters)
{[%Collection{}, ...], total_pages}Filter options:
:status- Filter by collection status (draft, pending, published, archived):access_level- Filter by access level (public, private, restricted):collection_type- Filter by collection type (series, book, movie, etc.):creator_id- Filter by creator/author ID:node_id- Filter by node/location ID:type_id- Filter by resource class ID:parent_filter- Filter hierarchy: "root" (no parent), "child" (has parent), or "all"
Get collections organized in a hierarchical tree structure. Now with pagination to prevent loading too many records at once.
Examples
iex> list_collections_tree()
[%Collection{children: [%Collection{}, ...]}, ...]
Returns the list of item_field_values.
Examples
iex> list_item_field_values()
[%ItemFieldValue{}, ...]
Returns the list of items.
Examples
iex> list_items()
[%Item{}, ...]
List items with pagination, search, and filters.
Examples
iex> list_items_paginated(1, 10, "book", %{node_id: 5})
{[%Item{}, ...], 3}
iex> list_items_paginated(1, 10, nil, %{status: "active"})
{[%Item{}, ...], 5}
Get list of collections with status 'pending' for review.
Examples
iex> list_pending_collections()
[%Collection{status: "pending"}, ...]
Get paginated list of pending collections for review.
Supports optional filtering/search and sort order.
Examples
iex> list_pending_collections_paginated(1, 10)
{[%Collection{}], total_pages, total_count}
iex> list_pending_collections_paginated(1, 10, nil, nil, nil, nil, "desc")
# newest items firstParameters
page- page numberper_page- results per page_user- (unused) user for scoping/filteringsearch_query- optional string to match against title, node, creator, etc.filter_status- filter by specific status ("pending"/"draft")node_id- restrict to a particular node (for non-superadmins)sort_order- "asc" for oldest first, "desc" for newest first
Get pending transfer requests for a specific node (target node).
Get collections suitable for being parents (excludes the given collection itself and its descendants).
Examples
iex> list_potential_parent_collections(collection_id)
[%Collection{}, ...]
Get root collections (collections without parents).
Examples
iex> list_root_collections()
[%Collection{}, ...]
Get paginated list of collections submitted by a specific user.
Examples
iex> list_submitted_collections_paginated(user, 1, 10, "search term")
{[%Collection{}], total_pages, total_count}
Get transfer request history for an item.
Returns the list of transfer_requests with optional filtering.
Examples
iex> list_transfer_requests()
[%TransferRequest{}, ...]
iex> list_transfer_requests(%{status: "pending"})
[%TransferRequest{status: "pending"}, ...]
Load the polymorphic attachable entity (collection or item) for an attachment
Reject a collection (change status from 'pending' to 'draft'). Note: requires reviewed_at, reviewed_by_id, review_notes fields in collections table.
Examples
iex> reject_collection(collection, reviewer_user, "Needs more information")
{:ok, %Collection{status: "draft"}}
Remove and nilify the thumbnail of an existing collection.
Reorder attachments for an entity
Reviews a transfer request (approve or deny).
Search attachments by filename or description
Search collections across all nodes without scoping. This is used by the collection search workflow to help librarians find existing collections regardless of location.
Returns collections with their node information and creator details.
Search for potential parent collections by title. Returns limited results for performance.
Examples
iex> search_potential_parent_collections("Harry", collection_id)
[%Collection{}, ...]
Set attachment as primary (unsets other primary attachments for the same entity)
Update attachment
Updates a collection.
Examples
iex> update_collection(collection, %{field: new_value})
{:ok, %Collection{}}
iex> update_collection(collection, %{field: bad_value})
{:error, %Ecto.Changeset{}}
Updates a collection_field.
Examples
iex> update_collection_field(collection_field, %{field: new_value})
{:ok, %CollectionField{}}
iex> update_collection_field(collection_field, %{field: bad_value})
{:error, %Ecto.Changeset{}}
Updates a item.
Examples
iex> update_item(item, %{field: new_value})
{:ok, %Item{}}
iex> update_item(item, %{field: bad_value})
{:error, %Ecto.Changeset{}}
Updates a item_field_value.
Examples
iex> update_item_field_value(item_field_value, %{field: new_value})
{:ok, %ItemFieldValue{}}
iex> update_item_field_value(item_field_value, %{field: bad_value})
{:error, %Ecto.Changeset{}}
Updates a transfer_request.