Voile.Schema.Catalog (Voile v0.1.27)

Copy Markdown View Source

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 item_field_value.

Creates a transfer_request.

Delete attachment and its file using the storage system

Deletes a item_field_value.

Deletes 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.

Get list of collections with status 'pending' 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 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)

Functions

apply_role_based_filters(user, filters)

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_collection(collection, reviewer_user, notes \\ nil)

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"}}

approve_transfer_request(transfer_request, reviewed_by_id)

Approves a transfer request and executes the location transfer.

barcode_prefix_exists(prefix, exclude_id \\ nil)

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")
false

Parameters

  • 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_collections(collections, reviewer_user, notes \\ nil)

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_collections(collections, reviewer_user, reason)

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}]}

cancel_transfer_request(transfer_request)

Cancels a transfer request (by requester).

change_collection(collection, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking collection changes.

Examples

iex> change_collection(collection)
%Ecto.Changeset{data: %Collection{}}

change_collection_field(collection_field, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking collection_field changes.

Examples

iex> change_collection_field(collection_field)
%Ecto.Changeset{data: %CollectionField{}}

change_item(item, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking item changes.

Examples

iex> change_item(item)
%Ecto.Changeset{data: %Item{}}

change_item_field_value(item_field_value, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking item_field_value changes.

Examples

iex> change_item_field_value(item_field_value)
%Ecto.Changeset{data: %ItemFieldValue{}}

change_transfer_request(transfer_request, attrs \\ %{})

Returns an %Ecto.Changeset{} for tracking transfer_request changes.

count_collections()

count_collections(unit_id)

count_collections_by_status()

count_collections_by_status(unit_id)

count_items()

count_items(unit_id)

count_items_by_availability()

count_items_by_availability(unit_id)

count_items_by_collection(collection_id)

count_pending_collections()

Count pending collections.

Examples

iex> count_pending_collections()
5

create_attachment(entity, params)

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_attachments(entity, files_params)

Create multiple attachments for an entity

create_collection(attrs \\ %{}, user_id \\ nil)

Creates a collection.

Examples

iex> create_collection(%{field: value})
{:ok, %Collection{}}

iex> create_collection(%{field: bad_value})
{:error, %Ecto.Changeset{}}

create_collection_field(attrs \\ %{}, user_id \\ nil)

Creates a collection_field.

Examples

iex> create_collection_field(%{field: value})
{:ok, %CollectionField{}}

iex> create_collection_field(%{field: bad_value})
{:error, %Ecto.Changeset{}}

create_item(attrs \\ %{}, user_id \\ nil)

Creates a item.

Examples

iex> create_item(%{field: value})
{:ok, %Item{}}

iex> create_item(%{field: bad_value})
{:error, %Ecto.Changeset{}}

create_item_field_value(attrs \\ %{})

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{}}

create_transfer_request(attrs \\ %{})

Creates a transfer_request.

delete_attachment(attachment)

Delete attachment and its file using the storage system

delete_collection(collection, user_id \\ nil)

Deletes a collection.

Examples

iex> delete_collection(collection)
{:ok, %Collection{}}

iex> delete_collection(collection)
{:error, %Ecto.Changeset{}}

delete_collection_field(collection_field, user_id \\ nil)

Deletes a collection_field.

Examples

iex> delete_collection_field(collection_field)
{:ok, %CollectionField{}}

iex> delete_collection_field(collection_field)
{:error, %Ecto.Changeset{}}

delete_item(item, user_id \\ nil)

Deletes a item.

Examples

iex> delete_item(item)
{:ok, %Item{}}

iex> delete_item(item)
{:error, %Ecto.Changeset{}}

delete_item_field_value(item_field_value)

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{}}

delete_transfer_request(transfer_request)

Deletes a transfer_request.

deny_transfer_request(transfer_request, reviewed_by_id, notes \\ nil)

Denies a transfer request.

find_item_by_barcode(code)

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_attachment!(id)

Get one attachments based on the id

get_attachment_stats(entity)

Get attachment statistics for an entity

get_collection!(id)

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)

get_collection_field(id)

get_collection_field!(id)

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_collection_path(collection)

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_collection_review_notes(collection_id)

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

get_collections_by_barcode_prefix(prefix)

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_for_review(ids)

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_url(attachment)

Get file path for serving

get_item(id)

get_item!(id)

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_item_by_code(item_code)

Get a single item based on the item_code passed. Returns nil if not found.

get_item_by_code!(item_code)

Get a single item based on the item_code passed.

get_item_by_code_or_barcode(identifier)

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

get_item_field_value!(id)

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_items_by_collection(collection_id)

get_items_by_collection(collection_id, user)

get_primary_attachment(arg1)

Get primary attachment for an entity

get_submitted_collections_status_counts(user)

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}

get_transfer_request!(id)

Gets a single transfer_request.

is_user_admin?(user)

Check if a user is an admin. Admins can see all collections without restrictions.

item_available?(item_id)

list_all_attachments(file_type \\ nil)

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)

list_attachments(arg1)

Get all attachments for an entity

list_attachments_by_type(entity, file_type)

Get attachments filtered by file type

list_available_items()

list_available_items_paginated(page \\ 1, per_page \\ 10)

list_children_collections(parent_id)

Get child collections for a given parent collection.

Examples

iex> list_children_collections(parent_id)
[%Collection{}, ...]

list_collection_fields()

Returns the list of collection_fields.

Examples

iex> list_collection_fields()
[%CollectionField{}, ...]

list_collections()

Returns the list of collections.

Examples

iex> list_collections()
[%Collection{}, ...]

list_collections_for_user(user, page \\ 1, per_page \\ 10, search \\ nil, filters \\ %{})

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}

list_collections_paginated(page \\ 1, per_page \\ 10, search \\ nil, filters \\ %{})

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"

list_collections_tree(limit \\ 100)

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{}, ...]}, ...]

list_item_field_values()

Returns the list of item_field_values.

Examples

iex> list_item_field_values()
[%ItemFieldValue{}, ...]

list_items()

Returns the list of items.

Examples

iex> list_items()
[%Item{}, ...]

list_items_paginated(page \\ 1, per_page \\ 10, search \\ nil, filters \\ %{})

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}

list_pending_collections()

Get list of collections with status 'pending' for review.

Examples

iex> list_pending_collections()
[%Collection{status: "pending"}, ...]

list_pending_collections_paginated(page \\ 1, per_page \\ 10, user \\ nil, search_query \\ nil, filter_status \\ nil, node_id \\ nil, sort_order \\ "asc")

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 first

Parameters

  • page - page number
  • per_page - results per page
  • _user - (unused) user for scoping/filtering
  • search_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

list_pending_transfers_for_node(node_id)

Get pending transfer requests for a specific node (target node).

list_potential_parent_collections(collection_id \\ nil)

Get collections suitable for being parents (excludes the given collection itself and its descendants).

Examples

iex> list_potential_parent_collections(collection_id)
[%Collection{}, ...]

list_root_collections()

Get root collections (collections without parents).

Examples

iex> list_root_collections()
[%Collection{}, ...]

list_submitted_collections_paginated(user, page \\ 1, per_page \\ 10, search \\ "", status \\ "all")

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}

list_transfer_history_for_item(item_id)

Get transfer request history for an item.

list_transfer_requests(filters \\ %{})

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_attachable(attachment)

Load the polymorphic attachable entity (collection or item) for an attachment

reject_collection(collection, reviewer_user, reason)

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_thumbnail(collection)

Remove and nilify the thumbnail of an existing collection.

reorder_attachments(entity, attachment_ids)

Reorder attachments for an entity

review_transfer_request(transfer_request, attrs)

Reviews a transfer request (approve or deny).

search_attachments(entity, query)

Search attachments by filename or description

search_collections(query_string)

search_collections(query_string, user)

search_collections_all_nodes(query_string)

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_items(query_string)

search_items(query_string, user)

search_items_paginated(query_string, page \\ 1, per_page \\ 10)

search_potential_parent_collections(search_term, collection_id \\ nil, limit \\ 10)

Search for potential parent collections by title. Returns limited results for performance.

Examples

iex> search_potential_parent_collections("Harry", collection_id)
[%Collection{}, ...]

set_primary_attachment(attachment)

Set attachment as primary (unsets other primary attachments for the same entity)

update_attachment(attachment, attrs)

Update attachment

update_collection(collection, attrs, user_id \\ nil)

Updates a collection.

Examples

iex> update_collection(collection, %{field: new_value})
{:ok, %Collection{}}

iex> update_collection(collection, %{field: bad_value})
{:error, %Ecto.Changeset{}}

update_collection_field(collection_field, attrs, user_id \\ nil)

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{}}

update_item(item, attrs, user_id \\ nil)

Updates a item.

Examples

iex> update_item(item, %{field: new_value})
{:ok, %Item{}}

iex> update_item(item, %{field: bad_value})
{:error, %Ecto.Changeset{}}

update_item_field_value(item_field_value, attrs)

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{}}

update_transfer_request(transfer_request, attrs)

Updates a transfer_request.