Packages

Sistema de libro contable para transacciones multi-moneda desarrollado como trabajo práctico para la materia Taller de Programación.

Current section

Files

Jump to
ledger_tp2 lib ledger moneda.ex
Raw

lib/ledger/moneda.ex

defmodule Ledger.Moneda do
@moduledoc """
Módulo para manejar monedas en el sistema Ledger.
Proporciona funciones para crear, listar y gestionar monedas.
"""
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias Ledger.Transaccion
alias Ledger.{Repo, FileHandler}
schema "monedas" do
field(:nombre, :string)
field(:precio_usd, :float)
timestamps()
end
@doc """
Crea una nueva moneda con el nombre y el precio en dólares proporcionados.
## Parámetros
- `nombre`: Nombre de la moneda (3-4 caracteres).
- `precio_usd`: Precio de la moneda en dólares (número no negativo).
## Retorno
- `{:ok, moneda}` si la moneda fue creada exitosamente.
- `{:error, razón}` si ocurrió algún error durante la creación.
"""
def crear_moneda(nombre, precio_usd) do
changeset =
%__MODULE__{}
|> changeset_crear(%{
nombre: String.upcase(nombre),
precio_usd: precio_usd
})
case Repo.insert(changeset) do
{:ok, moneda} ->
{:ok, moneda}
{:error, _razon} ->
{:error, FileHandler.extraer_error(changeset)}
end
end
@doc """
Obtiene una moneda por su ID.
## Parámetros
- `id`: ID de la moneda.
## Retorno
- `{:ok, moneda}` si la moneda fue encontrada.
- `{:error, razón}` si la moneda no fue encontrada.
"""
def obtener_moneda(id) do
case Repo.get(Ledger.Moneda, id) do
nil -> {:error, "Moneda no encontrada"}
moneda -> {:ok, moneda}
end
end
@doc """
Edita el precio en dólares de una moneda existente.
## Parámetros
- `id`: ID de la moneda.
- `nuevo_precio_usd`: Nuevo precio en dólares para la moneda.
## Retorno
- `{:ok, moneda}` si la moneda fue editada exitosamente.
- `{:error, razón}` si ocurrió algún error durante la edición.
"""
def editar_moneda(id, nuevo_precio_usd) do
with {:ok, moneda} <- obtener_moneda(id) do
changeset =
moneda
|> changeset_editar(%{
precio_usd: nuevo_precio_usd
})
case Repo.update(changeset) do
{:ok, moneda} ->
{:ok, moneda}
{:error, _} ->
{:error, FileHandler.extraer_error(changeset)}
end
end
end
@doc """
Borra una moneda por su ID.
## Parámetros
- `id`: ID de la moneda.
## Retorno
- `{:ok, mensaje}` si la moneda fue borrada exitosamente.
- `{:error, razón}` si ocurrió algún error durante el borrado.
"""
def borrar_moneda(id) do
with {:ok, moneda} <- obtener_moneda(id),
:ok <- puede_borrarse?(id),
{:ok, _} <- Repo.delete(moneda) do
{:ok, "Moneda borrada exitosamente"}
end
end
@doc """
Muestra la información de una moneda.
## Parámetros
- `id`: ID de la moneda.
- `archivo`: Archivo donde se mostrará la información o "stdout" para mostrar por salida estándar.
## Retorno
- `{:ok, informacion}` si la información fue mostrada exitosamente.
- `{:error, razón}` si ocurrió algún error al obtener la moneda.
"""
def ver_moneda(id, archivo) do
with {:ok, moneda} <- obtener_moneda(id) do
{:ok, FileHandler.mostrar_moneda(moneda, archivo)}
end
end
@doc """
Cambia un monto de una moneda a otra utilizando sus precios en dólares.
## Parámetros
- `monto`: Monto a convertir.
- `precio_origen`: Precio en dólares de la moneda de origen.
- `precio_destino`: Precio en dólares de la moneda de destino.
## Retorno
- `{:ok, monto_convertido}` con el monto convertido.
"""
def cambiar_a_moneda(monto, precio_origen, precio_destino) do
{:ok, monto * precio_origen / precio_destino}
end
@doc """
Obtiene el nombre de una moneda por su ID.
## Parámetros
- `id`: ID de la moneda.
## Retorno
- `nombre` de la moneda si fue encontrada.
- `{:error, razón}` si la moneda no fue encontrada.
"""
def obtener_nombre(id) do
with {:ok, moneda} <- obtener_moneda(id) do
moneda.nombre
end
end
@doc """
Obtiene el precio en dólares de una moneda por su ID.
## Parámetros
- `id`: ID de la moneda.
## Retorno
- `precio_usd` de la moneda si fue encontrada.
- `{:error, razón}` si la moneda no fue encontrada.
"""
def obtener_precio(id) do
with {:ok, moneda} <- obtener_moneda(id) do
moneda.precio_usd
end
end
defp changeset_crear(moneda, attrs) do
moneda
|> cast(attrs, [:nombre, :precio_usd])
|> validate_required(:nombre, message: "El nombre es obligatorio")
|> validate_required(:precio_usd, message: "El precio en dólares es obligatorio")
|> unique_constraint(:nombre)
|> validate_number(:precio_usd,
greater_than_or_equal_to: 0,
message: "El precio debe ser un número mayor o igual a 0"
)
|> validate_format(:nombre, ~r/^[A-Z]{3,4}$/,
message: "El nombre de la moneda debe tener entre 3 y 4 caracteres"
)
end
defp changeset_editar(moneda, attrs) do
moneda
|> cast(attrs, [:precio_usd])
|> validate_required([:precio_usd], message: "El precio es obligatorio")
|> unique_constraint(:nombre)
|> validate_number(:precio_usd,
greater_than: 0,
message: "El precio debe ser un número positivo"
)
end
defp puede_borrarse?(id) do
transacciones =
Repo.all(
from(t in Transaccion,
where: (t.moneda_origen_id == ^id or t.moneda_destino_id == ^id) and t.tipo != "alta"
)
)
if Enum.empty?(transacciones) do
:ok
else
{:error, "La moneda tiene transacciones asociadas"}
end
end
end