DoubleEntryLedger.Workers.CommandWorker.CreateAccountCommandMapNoSaveOnError (double_entry_ledger v0.4.0)
View SourceProcesses AccountCommandMap for creating new accounts in the double-entry ledger system.
This worker handles the creation of accounts based on validated AccountCommandMap data. It coordinates the creation of both the Command record (for audit trail) and the Account record (the actual ledger account) within a single database transaction.
Unlike standard command processors, this module does not persist error states to the database. Instead, it returns validation errors as changesets for client handling, making it suitable for scenarios where error persistence should be managed externally.
Processing Flow
- Command Creation: Creates a Command record from the AccountCommandMap for audit purposes
- Account Creation: Creates the Account record using the payload data
- Command Completion: Marks the command as processed upon successful account creation
- Linking: Creates a link between the command and the created account for traceability
Error Handling
The module provides detailed error handling and logging:
- Command validation errors are mapped back to AccountCommandMap changesets
- Account validation errors are propagated to the command map payload
- All processing steps are logged with appropriate trace information
- Database transaction ensures atomicity (all-or-nothing)
- Errors are returned as changesets rather than persisted to the database
Key Features
- Transactional Safety: Uses Ecto.Multi for atomic operations
- Error Propagation: Maps validation errors back to appropriate changeset structures
- Audit Trail: Creates command records for all account creation attempts
- Traceability: Links commands to created accounts for audit purposes
- No Error Persistence: Returns error changesets without database persistence
Supported Actions
Currently supports:
:create_account- Creates a new account from AccountCommandMap payload
Summary
Functions
Processes an AccountCommandMap to create a new account in the ledger system.
Functions
@spec process(DoubleEntryLedger.Command.AccountCommandMap.t()) :: DoubleEntryLedger.Workers.CommandWorker.AccountCommandMapResponseHandler.response()
Processes an AccountCommandMap to create a new account in the ledger system.
This function orchestrates the creation of both a Command record (for audit trail) and an Account record within a single database transaction. Upon successful completion, the command is marked as processed and linked to the created account.
Parameters
command_map: AccountCommandMap struct containing validated account creation data. Must have:create_accountaction.
Returns
{:ok, account, command}- Success tuple containing the created Account and Command{:error, changeset}- AccountCommandMap changeset with validation errors when command or account creation fails{:error, message}- String error message for unexpected failures
Transaction Steps
- Creates Command record from AccountCommandMap
- Creates Account record from payload data
- Marks Command as processed
- Creates Command-Account link for traceability
Error Mapping
- Command validation errors → AccountCommandMap changeset with command-level errors
- Account validation errors → AccountCommandMap changeset with payload-level errors
- Other failures → String error message with details
Examples
# Successful account creation
iex> {:ok, instance} = InstanceStore.create(%{address: "Main:Instance"})
iex> command_map = %AccountCommandMap{
...> action: :create_account,
...> source: "test_suite",
...> instance_address: instance.address,
...> payload: %AccountData{
...> name: "Cash Account",
...> address: "account:main",
...> type: :asset,
...> currency: :USD
...> }
...> }
iex> {:ok, account, event} = CreateAccountCommandMapNoSaveOnError.process(command_map)
iex> is_struct(account, Account) and account.name == "Cash Account" and is_struct(event, Command) and event.command_queue_item.status == :processed
true
iex> {:ok, instance} = InstanceStore.create(%{address: "Main:Instance"})
iex> invalid_command_map = %AccountCommandMap{
...> action: :create_account,
...> source: "test_suite",
...> instance_address: instance.address,
...> payload: %AccountData{name: "", type: nil} # missing required fields
...> }
iex> {:error, changeset} = CreateAccountCommandMapNoSaveOnError.process(invalid_command_map)
iex> changeset.valid?
false