webmoney/backend/app/Http/Controllers/Api/FinancialGoalController.php
marco 54cccdd095 refactor: migração para desenvolvimento direto no servidor
- Removido README.md padrão do Laravel (backend)
- Removidos scripts de deploy (não mais necessários)
- Atualizado copilot-instructions.md para novo fluxo
- Adicionada documentação de auditoria do servidor
- Sincronizado código de produção com repositório

Novo workflow:
- Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney)
- Mudanças PHP são instantâneas
- Mudanças React requerem 'npm run build'
- Commit após validação funcional
2025-12-19 11:45:32 +01:00

199 lines
6.3 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\FinancialGoal;
use App\Models\GoalContribution;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class FinancialGoalController extends Controller
{
/**
* Listar todas las metas del usuario
*/
public function index(Request $request)
{
$query = FinancialGoal::forUser(Auth::id())
->with('contributions')
->orderByRaw("FIELD(status, 'active', 'paused', 'completed', 'cancelled')")
->orderBy('priority', 'desc')
->orderBy('target_date', 'asc');
if ($request->has('status')) {
$query->where('status', $request->status);
}
$goals = $query->get();
// Calcular estadísticas generales
$activeGoals = $goals->where('status', 'active');
$stats = [
'total_goals' => $goals->count(),
'active_goals' => $activeGoals->count(),
'completed_goals' => $goals->where('status', 'completed')->count(),
'total_target' => $activeGoals->sum('target_amount'),
'total_saved' => $activeGoals->sum('current_amount'),
'overall_progress' => $activeGoals->sum('target_amount') > 0
? round(($activeGoals->sum('current_amount') / $activeGoals->sum('target_amount')) * 100, 1)
: 0,
];
return response()->json([
'data' => $goals,
'stats' => $stats,
]);
}
/**
* Crear una nueva meta
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'icon' => 'nullable|string|max:50',
'color' => 'nullable|string|max:20',
'target_amount' => 'required|numeric|min:0.01',
'current_amount' => 'nullable|numeric|min:0',
'currency' => 'nullable|string|size:3',
'target_date' => 'nullable|date|after:today',
'start_date' => 'nullable|date',
'monthly_contribution' => 'nullable|numeric|min:0',
'priority' => 'nullable|in:high,medium,low',
]);
$validated['user_id'] = Auth::id();
$validated['start_date'] = $validated['start_date'] ?? now()->format('Y-m-d');
$goal = FinancialGoal::create($validated);
// Si tiene monto inicial, crear contribución
if (isset($validated['current_amount']) && $validated['current_amount'] > 0) {
$goal->contributions()->create([
'amount' => $validated['current_amount'],
'contribution_date' => $validated['start_date'],
'notes' => 'Monto inicial',
]);
}
return response()->json([
'message' => 'Meta creada con éxito',
'data' => $goal->fresh('contributions'),
], 201);
}
/**
* Ver una meta específica
*/
public function show($id)
{
$goal = FinancialGoal::forUser(Auth::id())
->with(['contributions' => function($q) {
$q->orderBy('contribution_date', 'desc');
}])
->findOrFail($id);
return response()->json($goal);
}
/**
* Actualizar una meta
*/
public function update(Request $request, $id)
{
$goal = FinancialGoal::forUser(Auth::id())->findOrFail($id);
$validated = $request->validate([
'name' => 'sometimes|string|max:255',
'description' => 'nullable|string',
'icon' => 'nullable|string|max:50',
'color' => 'nullable|string|max:20',
'target_amount' => 'sometimes|numeric|min:0.01',
'target_date' => 'nullable|date',
'monthly_contribution' => 'nullable|numeric|min:0',
'status' => 'sometimes|in:active,completed,paused,cancelled',
'priority' => 'sometimes|in:high,medium,low',
]);
$goal->update($validated);
// Si se marca como completada manualmente
if (isset($validated['status']) && $validated['status'] === 'completed' && !$goal->completed_at) {
$goal->completed_at = now();
$goal->save();
}
return response()->json([
'message' => 'Meta actualizada',
'data' => $goal->fresh('contributions'),
]);
}
/**
* Eliminar una meta
*/
public function destroy($id)
{
$goal = FinancialGoal::forUser(Auth::id())->findOrFail($id);
$goal->delete();
return response()->json([
'message' => 'Meta eliminada',
]);
}
/**
* Añadir contribución a una meta
*/
public function addContribution(Request $request, $id)
{
$goal = FinancialGoal::forUser(Auth::id())->findOrFail($id);
$validated = $request->validate([
'amount' => 'required|numeric|min:0.01',
'contribution_date' => 'nullable|date',
'transaction_id' => 'nullable|exists:transactions,id',
'notes' => 'nullable|string',
]);
$contribution = $goal->addContribution(
$validated['amount'],
$validated['contribution_date'] ?? now(),
$validated['transaction_id'] ?? null,
$validated['notes'] ?? null
);
return response()->json([
'message' => 'Contribución añadida',
'data' => $goal->fresh('contributions'),
]);
}
/**
* Eliminar contribución
*/
public function removeContribution($goalId, $contributionId)
{
$goal = FinancialGoal::forUser(Auth::id())->findOrFail($goalId);
$contribution = $goal->contributions()->findOrFail($contributionId);
// Restar el monto de la meta
$goal->current_amount -= $contribution->amount;
if ($goal->status === 'completed') {
$goal->status = 'active';
$goal->completed_at = null;
}
$goal->save();
$contribution->delete();
return response()->json([
'message' => 'Contribución eliminada',
'data' => $goal->fresh('contributions'),
]);
}
}