Packages
ledger_tp2
0.1.0
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
Current section
Files
lib/ledger/usuario.ex
defmodule Ledger.Usuario do
@moduledoc """
Módulo para manejar usuarios en el sistema Ledger.
Proporciona funciones para crear, listar y gestionar usuarios.
"""
use Ecto.Schema
import Ecto.Changeset
alias Ledger.{Repo, FileHandler, Transaccion}
schema "usuarios" do
field(:nombre, :string)
field(:fecha_nacimiento, :date)
timestamps()
end
@doc """
Crea un nuevo usuario con el nombre y la fecha de nacimiento proporcionados.
## Parámetros
- `nombre`: Nombre del usuario.
- `fecha_nacimiento`: Fecha de nacimiento en formato ISO8601 (AAAA-MM-DD).
## Retorno
- `{:ok, usuario}` si el usuario fue creado exitosamente.
- `{:error, razón}` si ocurrió algún error durante la creación.
"""
def crear_usuario(nombre, fecha_nacimiento) do
case Date.from_iso8601(fecha_nacimiento) do
{:ok, fecha} ->
changeset =
%__MODULE__{}
|> crear_changeset(%{
nombre: nombre,
fecha_nacimiento: fecha
})
case Repo.insert(changeset) do
{:ok, usuario} ->
{:ok, usuario}
{:error, _razon} ->
{:error, FileHandler.extraer_error(changeset)}
end
{:error, _} ->
{:error, "Fecha de nacimiento inválida. Formato esperado: AAAA-MM-DD"}
end
end
@doc """
Obtiene un usuario por su ID.
## Parámetros
- `id`: ID del usuario.
## Retorno
- `{:ok, usuario}` si el usuario fue encontrado.
- `{:error, razón}` si el usuario no fue encontrado.
"""
def obtener_usuario(id) do
case Repo.get(Ledger.Usuario, id) do
nil -> {:error, "Usuario no encontrado"}
usuario -> {:ok, usuario}
end
end
@doc """
Edita el nombre de un usuario existente.
## Parámetros
- `id`: ID del usuario.
- `nuevo_nombre`: Nuevo nombre para el usuario.
## Retorno
- `{:ok, usuario}` si el usuario fue editado exitosamente.
- `{:error, razón}` si ocurrió algún error durante la edición.
"""
def editar_usuario(id, nuevo_nombre) do
with {:ok, usuario} <- obtener_usuario(id) do
if nuevo_nombre == "" do
{:error, "El nombre es obligatorio"}
else
changeset =
usuario
|> editar_changeset(%{
nombre: nuevo_nombre
})
case Repo.update(changeset) do
{:ok, usuario} ->
{:ok, usuario}
{:error, _razon} ->
{:error, FileHandler.extraer_error(changeset)}
end
end
end
end
@doc """
Borra un usuario por su ID.
## Parámetros
- `id`: ID del usuario.
## Retorno
- `{:ok, mensaje}` si el usuario fue borrado exitosamente.
- `{:error, razón}` si ocurrió algún error durante el borrado.
"""
def borrar_usuario(id) do
with {:ok, usuario} <- obtener_usuario(id),
:ok <- puede_borrarse(id),
{:ok, _} <- Repo.delete(usuario) do
{:ok, "Usuario borrado exitosamente"}
end
end
@doc """
Muestra la información de un usuario.
## Parámetros
- `id`: ID del usuario.
- `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 el usuario.
"""
def ver_usuario(id, archivo) do
with {:ok, usuario} <- obtener_usuario(id) do
{:ok, FileHandler.mostrar_usuario(usuario, archivo)}
end
end
defp crear_changeset(usuario, attrs) do
usuario
|> cast(attrs, [:nombre, :fecha_nacimiento])
|> validate_required(:nombre, message: "El nombre es obligatorio")
|> validate_required(:fecha_nacimiento)
|> unique_constraint(:nombre, message: "El nombre ya está en uso")
|> validar_mayoria_edad(:fecha_nacimiento)
end
defp editar_changeset(usuario, attrs) do
usuario
|> cast(attrs, [:nombre])
|> validate_required(:nombre, message: "El nombre es obligatorio")
|> unique_constraint(:nombre, message: "El nombre ya está en uso")
|> validar_nombre_distinto(usuario)
end
defp validar_mayoria_edad(changeset, fecha) do
case get_field(changeset, fecha) do
nil ->
changeset
fecha_nacimiento ->
años = Date.diff(Date.utc_today(), fecha_nacimiento) |> div(365)
if años < 18 do
add_error(changeset, fecha, "El usuario debe ser mayor de edad")
else
changeset
end
end
end
defp validar_nombre_distinto(changeset, usuario) do
nuevo_nombre = get_field(changeset, :nombre)
if nuevo_nombre == usuario.nombre do
add_error(changeset, :nombre, "El nuevo nombre debe ser distinto al actual")
else
changeset
end
end
defp puede_borrarse(id) do
with {:ok, transacciones_salientes} <- Transaccion.obtener_transacciones(id, ""),
{:ok, transacciones_entrantes} <- Transaccion.obtener_transacciones("", id) do
transacciones = transacciones_salientes ++ transacciones_entrantes
transacciones_no_alta = Enum.filter(transacciones, &(&1.tipo != "alta"))
if Enum.empty?(transacciones_no_alta) do
:ok
else
{:error, "El usuario tiene transacciones asociadas"}
end
end
end
end