DoubleEntryLedger.Stores.CommandStoreHelper (double_entry_ledger v0.2.0)

View Source

Helper functions for command processing in the Double Entry Ledger system.

This module provides reusable utilities for working with commands, focusing on common operations like building changesets, retrieving related commands and transactions, and creating multi operations for use in Ecto transactions.

Key Functionality

  • Changeset Building: Create Command changesets from TransactionCommandMaps or AccountCommandMaps
  • Command Relationships: Look up related commands by source identifiers
  • Transaction Linking: Find transactions and accounts associated with commands
  • Ecto.Multi Integration: Build multi operations for atomic database transactions
  • Status Management: Create changesets to update command status and error information

Usage Examples

Building a changeset from a CommandMap:

event_changeset = CommandStoreHelper.build_create(command_map)

Adding a step to get a create command's transaction:

multi =
  Ecto.Multi.new()
  |> CommandStoreHelper.build_get_create_transaction_command_transaction(:transaction, update_command)
  |> Ecto.Multi.update(:event, fn %{transaction: transaction} ->
    CommandStoreHelper.build_mark_as_processed(update_command, transaction.id)
  end)

Implementation Notes

This module is primarily used internally by CommandStore and CommandWorker modules to share common functionality and reduce code duplication.

Summary

Functions

Builds an Command changeset from a TransactionCommandMap or AccountCommandMap.

Builds an Ecto.Multi step to get a create-transaction command's transaction.

Retrieves a command by its action and source identifiers with preloaded associations.

Gets the transaction associated with a create-transaction command.

Functions

base_account_query(account_id)

@spec base_account_query(Ecto.UUID.t()) :: Ecto.Query.t()

base_transaction_query(transaction_id)

@spec base_transaction_query(Ecto.UUID.t()) :: Ecto.Query.t()

build_create(command_map, instance_id)

Builds an Command changeset from a TransactionCommandMap or AccountCommandMap.

Creates a new Command changeset suitable for database insertion, converting the provided command map structure into the appropriate Command attributes.

Parameters

  • command_map - Either a TransactionCommandMap or AccountCommandMap struct containing command data

Returns

  • Ecto.Changeset.t(Command.t()) - A changeset for creating a new Command

build_get_create_transaction_command_transaction(multi, step, command_or_step)

@spec build_get_create_transaction_command_transaction(
  Ecto.Multi.t(),
  atom(),
  DoubleEntryLedger.Command.t() | atom()
) :: Ecto.Multi.t()

Builds an Ecto.Multi step to get a create-transaction command's transaction.

This function adds a step to an Ecto.Multi that retrieves the transaction associated with the create command corresponding to an update command. Handles error cases by wrapping exceptions in the result tuple.

Parameters

  • multi - The Ecto.Multi instance to add the step to
  • step - The atom representing the step name in the Multi
  • command_or_step - Either a Command struct or the name of a previous step in the Multi

Returns

  • Ecto.Multi.t() - The updated Multi instance with the new step added

get_command_by(action, source, source_idempk, instance_id)

@spec get_command_by(atom(), String.t(), String.t(), Ecto.UUID.t()) ::
  DoubleEntryLedger.Command.t() | nil

Retrieves a command by its action and source identifiers with preloaded associations.

This function looks up a command using its action,

command_map
|> TransactionCommandMap.to_map()
|> Map.put(:instance_id, instance_id)
|> Mts action, source system identifier,

source-specific identifier, and instance ID. The returned command includes preloaded associations for command_queue_item, account, and transaction with its entries.

Parameters

  • action: The command action atom (e.g., :create_transaction, :create_account)
  • source: The source system identifier (e.g., "accounting_system", "api")
  • source_idempk: The source-specific identifier (e.g., "invoice_123", "tx_456")
  • instance_id: The instance UUID that groups related events

Returns

  • Command.t() | nil: The found command with preloaded associations, or nil if not found

Preloaded Associations

The returned command includes:

  • :command_queue_item - Processing status and retry information
  • :account - Associated account (for account-related events)
  • transaction: [entries: :account] - Transaction with its entries and accounts

get_create_transaction_command_transaction(command)

@spec get_create_transaction_command_transaction(DoubleEntryLedger.Command.t()) ::
  {:ok, {DoubleEntryLedger.Transaction.t(), DoubleEntryLedger.Command.t()}}
  | {:error | :pending_error, String.t(), DoubleEntryLedger.Command.t() | nil}

Gets the transaction associated with a create-transaction command.

This function finds the original create transaction command corresponding to an update command and returns its associated transaction. Used primarily when processing update events to locate the original transaction to modify.

Parameters

  • update_command - A Command struct containing source, source_idempk, and instance_id

Returns

  • {:ok, {Transaction.t(), Command.t()}} - The transaction and create command if found and processed
  • Raises UpdateCommandError if the create command doesn't exist or isn't processed

transaction_events_for_account_query(account_id)

@spec transaction_events_for_account_query(Ecto.UUID.t()) :: Ecto.Query.t()