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'), ]); } }