webmoney/backend/app/Http/Controllers/Api/UserPreferenceController.php
marcoitaloesp-ai 19dcdce262
feat: Add daily due payments notification system with user preferences
## New Features
- Email notifications for overdue and upcoming payments
- User preferences page for notification settings
- Daily scheduler to send alerts at user-configured time
- Smart analysis: payable items, transfer suggestions between accounts

## Backend
- Migration for user_preferences table
- SendDuePaymentsAlert Artisan command
- DuePaymentsAlert Mailable with HTML/text templates
- UserPreferenceController with test-notification endpoint
- Scheduler config for notify:due-payments command

## Frontend
- Preferences.jsx page with notification toggle
- API service for preferences
- Route and menu link for settings
- Translations (PT-BR, EN, ES)

## Server
- Cron configured for Laravel scheduler

Version: 1.44.5
2025-12-17 09:57:40 +00:00

125 lines
4.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\UserPreference;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class UserPreferenceController extends Controller
{
/**
* Get user preferences
*/
public function index(Request $request): JsonResponse
{
$userId = $request->user()->id;
$preferences = UserPreference::firstOrCreate(
['user_id' => $userId],
[
'notify_due_payments' => false,
'notify_due_payments_time' => '20:00:00',
'notify_due_payments_email' => null,
'language' => 'pt-BR',
'timezone' => 'Europe/Madrid',
'currency' => 'EUR',
]
);
// Get raw time from database attribute (without datetime cast)
$rawTime = $preferences->getRawOriginal('notify_due_payments_time');
$timeFormatted = $rawTime ? substr($rawTime, 0, 5) : '20:00';
return response()->json([
'success' => true,
'data' => [
'notify_due_payments' => $preferences->notify_due_payments,
'notify_due_payments_time' => $timeFormatted,
'notify_due_payments_email' => $preferences->notify_due_payments_email,
'language' => $preferences->language,
'timezone' => $preferences->timezone,
'currency' => $preferences->currency,
'user_email' => $request->user()->email, // For display when custom email is null
],
]);
}
/**
* Update user preferences
*/
public function update(Request $request): JsonResponse
{
$validated = $request->validate([
'notify_due_payments' => 'sometimes|boolean',
'notify_due_payments_time' => 'sometimes|date_format:H:i',
'notify_due_payments_email' => 'sometimes|nullable|email',
'language' => 'sometimes|string|in:pt-BR,en,es',
'timezone' => 'sometimes|string|timezone',
'currency' => 'sometimes|string|in:EUR,USD,BRL,GBP',
]);
$userId = $request->user()->id;
$preferences = UserPreference::firstOrCreate(
['user_id' => $userId],
[
'notify_due_payments' => false,
'notify_due_payments_time' => '20:00:00',
'language' => 'pt-BR',
'timezone' => 'Europe/Madrid',
'currency' => 'EUR',
]
);
// Convert time to proper format if provided
if (isset($validated['notify_due_payments_time'])) {
$validated['notify_due_payments_time'] = $validated['notify_due_payments_time'] . ':00';
}
$preferences->update($validated);
return response()->json([
'success' => true,
'message' => 'Preferências atualizadas com sucesso',
'data' => [
'notify_due_payments' => $preferences->notify_due_payments,
'notify_due_payments_time' => substr($preferences->notify_due_payments_time, 0, 5),
'notify_due_payments_email' => $preferences->notify_due_payments_email,
'language' => $preferences->language,
'timezone' => $preferences->timezone,
'currency' => $preferences->currency,
],
]);
}
/**
* Test due payments notification (send immediately)
*/
public function testNotification(Request $request): JsonResponse
{
$userId = $request->user()->id;
try {
\Artisan::call('notify:due-payments', [
'--user' => $userId,
'--force' => true,
]);
$output = \Artisan::output();
return response()->json([
'success' => true,
'message' => 'Notificação de teste enviada! Verifique seu email.',
'output' => $output,
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Erro ao enviar notificação: ' . $e->getMessage(),
], 500);
}
}
}