Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juanVillamilEchavarria/Leo_Counter-app/llms.txt

Use this file to discover all available pages before exploring further.

Leo Counter’s notification system keeps household members informed about upcoming financial obligations without requiring them to log in and check manually. Administrators configure one or more named email channels, assign subscriber users to those channels, and the scheduler takes care of firing alerts when fixed movements become due or pending payments are approaching their deadline. The entire notification configuration lives under Configuración (/configuracion) and is restricted to users with the admin role.

Notification Channels (CanalNotificacion)

A notification channel represents a named email delivery pipeline. Each channel has an active flag that controls whether notifications actually get sent through it.
// database/migrations/2026_05_21_191547_create_canales_notificacion_table.php
$table->uuid('id')->primary();
$table->string('nombre')->unique();
$table->boolean('active')->default(false);
Currently, Leo Counter supports the Email channel type only, as defined by CanalesNotificacionEnum::EMAIL = 'Email'. Additional channel types (e.g. SMS, webhook) can be added in future releases.

Channel Routes

MethodURIAction
GET/canal-notificacionesList all channels
POST/canal-notificacionesCreate a channel
PUT/canal-notificaciones/{id}Update a channel
DELETE/canal-notificaciones/{id}Delete a channel
PATCH/canal-notificaciones/{id}/{attribute}/toggleToggle active flag (implemented)
The only action with a full controller implementation is the toggle. Toggle a channel on or off:
PATCH /canal-notificaciones/{canal}/{attribute}/toggle
Where {attribute} is active. The ToggleCanalCommand is dispatched and the boolean is flipped. After the update Leo Counter redirects back to /configuracion.
// app/Http/Controllers/Notificacion/CanalNotificacionController.php
public function toggle(string $id, string $atribute)
{
    $this->dispatcher->dispatch(new ToggleCanalCommand(id: $id, attribute: $atribute));
    Inertia::flash('success', 'Canal actualizado');
    return redirect()->route('configuracion.index');
}

Subscribers (SuscriptorNotificacion)

A subscriber pairs a user account with a notification channel. When a notification fires on a channel, every active and verified subscriber on that channel receives the email.
// database/migrations/2026_05_21_191548_create_suscriptores_notificaciones_table.php
$table->uuid('id')->primary();
$table->foreignUuid('user_id')->constrained('users');
$table->foreignUuid('canal_notificacion_id')->constrained('canales_notificacion');
$table->boolean('active')->default(true);
$table->timestamp('verified_at')->nullable();
$table->unique(['user_id', 'canal_notificacion_id']);
The verified_at field is null until the subscriber clicks the email verification link. Unverified subscribers do not receive notifications even if their active flag is true.

Creating a Subscriber

Subscribers are created by the admin using a form validated by StoreAndUpdateSuscriptorRequest:
// app/Http/Requests/Notificacion/StoreAndUpdateSuscriptorRequest.php
return [
    'user_id'              => ['required', 'string', 'exists:users,id'],
    'canal_notificacion_id'=> ['required', 'string', 'exists:canales_notificacion,id'],
];
When a subscriber is stored, StoreSuscriptorHandler dispatches an email verification message using SendEmailVerificationToSuscriptorStrategy. The email contains a signed URL that expires according to your application’s link expiry setting.

Subscriber Routes

Subscriber management is split across two controllers. The web SuscriptorController only provides the toggle endpoint. The API SuscriptorApiController provides the create, delete, and form-options endpoints consumed by the React front-end:
MethodURIControllerAction
GET/suscriptor-notificacionesWeb (resource index)List all subscribers
PATCH/suscriptor-notificaciones/{id}/{attribute}/toggleWeb SuscriptorControllerToggle active flag
POST/api/notificacion/suscriptoresAPI SuscriptorApiControllerAdd a subscriber
DELETE/api/notificacion/suscriptores/{id}API SuscriptorApiControllerRemove a subscriber
GET/api/notificacion/suscriptores/form-optionsAPI SuscriptorApiControllerSubscriber form options
Edit and update actions are intentionally excluded for subscribers. To change a subscriber’s channel, delete the existing subscription and create a new one. The store and destroy actions that actually persist changes are handled by the API controller at /api/notificacion/suscriptores, not the web resource route.

Email Verification

After an admin adds a subscriber, the user receives a verification email at their registered address. Clicking the link hits:
GET /suscriptores/verificar/{suscriptorId}
This route is protected by Laravel’s signed middleware so it cannot be tampered with. The SuscriptorVerificationController dispatches VerifySuscriptorCommand, which sets verified_at to the current timestamp and renders a confirmation view.
// app/Http/Controllers/Notificacion/SuscriptorVerificationController.php
public function verify(string $suscriptorId) {
    $this->commandBus->dispatch(new VerifySuscriptorCommand($suscriptorId));
    return view('notificaciones.suscriptores.verified');
}

Toggle Subscriber Active State

Admins can temporarily pause notifications for a specific subscriber without removing them:
PATCH /suscriptor-notificaciones/{suscriptor}/{attribute}/toggle
// app/Http/Controllers/Notificacion/SuscriptorController.php
public function toggle(string $id, string $attribute)
{
    $this->dispatcher->dispatch(new ToggleSuscriptorCommand(id: $id, attribute: $attribute));
    Inertia::flash('success', 'Suscripción actualizada');
    return redirect()->route('configuracion.index');
}

What Triggers Notifications

Notifications are fired by the daily financial tasks command, which processes two types of events:
  1. Fixed movements due — when a MovimientoFijo reaches its fecha_proximo (or is within the dias_aviso warning window), ProcessFinancialTaskForMovimientoFijoCommand is dispatched. If registrar_automatico = true, Leo Counter automatically registers a spontaneous movement (RegisterMovimientoFromMovimientoFijoCommand) and advances fecha_proximo to the next recurrence. If registrar_automatico = false, it creates a pending movement (RegisterMovimientoPendienteFromMovimientoFijoCommand) instead. In both cases, subscribers on active channels receive a warning alert when the dias_aviso threshold is reached.
  2. Pending payments due or expiredProcessFinancialTasksForMovimientoPendienteCommand scans pending movements. Movements approaching fecha_programada within the dias_aviso window trigger a warning notification (SendMessageToUsersWhenMovimientoPendienteWarningDayArrivedEventHandler). Movements whose fecha_programada has passed without being marked done trigger an expiry alert (SendMessageToUsersWhenMovimientoPendienteExpiredEventHandler) and transition their status to vencido.

The Daily Scheduler Command

// app/Console/Commands/ProcessDailyFinancialTasks.php
protected $signature    = 'leo:process-daily-financial-tasks';
protected $description  = 'Procesa las tareas financieras diarias';

public function handle()
{
    $this->commandBus->dispatch(new ProcessFinancialTaskForMovimientoFijoCommand());
    $this->commandBus->dispatch(new ProcessFinancialTasksForMovimientoPendienteCommand());
    $this->info('Tareas financieras diarias procesadas');
}
Run it manually:
php artisan leo:process-daily-financial-tasks
In production, the command is registered in the Laravel scheduler and executed automatically once per day by the scheduler container.
Notifications only fire if the scheduler container is running. In the Docker Compose development setup the scheduler service must be started explicitly. Verify it is up before testing notifications end-to-end.

Development Email Testing with Mailhog

During local development Leo Counter is pre-configured to route all outgoing email through Mailhog, an in-memory SMTP server that captures messages without sending them to real inboxes. Open the Mailhog web UI at:
http://localhost:8025
All verification emails and financial alert notifications will appear here. This lets you test the full notification flow — channel creation, subscriber enrollment, verification link, and daily task alerts — without touching real email addresses.

Setup Workflow

1

Create a notification channel

Log in as admin and navigate to Configuración. Under notification channels, click Create and enter a unique channel name (e.g. “Email Familia”). Toggle the channel to active once it is ready.
2

Add subscribers

Within the same configuration page, create a subscriber by selecting a Leo Counter user and linking them to the channel. Each user–channel pair is unique. The system immediately dispatches a verification email to the user.
3

Subscribers verify their email

Each subscriber receives an email with a signed verification link at /suscriptores/verificar/{id}. Clicking the link sets verified_at and activates their subscription.
4

Configure advance notice on movements

When creating fixed or pending movements, set dias_aviso to a positive integer to receive a warning email that many days before the due date. For example, dias_aviso = 3 sends an alert three days ahead.
5

Receive notifications automatically

Once the scheduler runs leo:process-daily-financial-tasks, all active, verified subscribers on active channels receive email alerts for any movements that are due that day or entering their warning window.

Build docs developers (and LLMs) love