acct_type, UserActions::ViewBarangayBudget); } private function checkWrite(): bool { return UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageBarangayBudget); } public function index(Request $request) { if (!$this->checkRead()) return ResponseHelper::returnUnauthorized(); $query = BarangayBudget::with('encodedBy')->orderByDesc('date'); if ($year = $request->input('year')) $query->byYear((int) $year); if ($category = $request->input('category')) $query->where('category', $category); $entries = $query->paginate((int) $request->input('per_page', 30)); return response()->json(['success' => true, 'data' => $entries]); } public function summary(Request $request) { if (!$this->checkRead()) return ResponseHelper::returnUnauthorized(); $year = (int) $request->input('year', date('Y')); $income = BarangayBudget::byYear($year)->income()->sum('amount'); $expense = BarangayBudget::byYear($year)->expense()->sum('amount'); $bySource = BarangayBudget::byYear($year) ->selectRaw('category, source, SUM(amount) as total') ->groupBy('category', 'source') ->orderBy('category') ->orderByDesc('total') ->get(); return response()->json([ 'success' => true, 'data' => [ 'year' => $year, 'income' => $income, 'expense' => $expense, 'balance' => $income - $expense, 'by_source' => $bySource, ], ]); } public function store(Request $request) { if (!$this->checkWrite()) return ResponseHelper::returnUnauthorized(); $validator = Validator::make($request->all(), [ 'fiscal_year' => 'required|integer|min:2020|max:2100', 'category' => 'required|in:INCOME,EXPENSE', 'source' => 'required|string|max:255', 'amount' => 'required|numeric|min:0.01', 'description' => 'nullable|string|max:500', 'date' => 'required|date', 'reference' => 'nullable|string|max:100', ]); if ($validator->fails()) { return response()->json(['success' => false, 'errors' => $validator->errors()], 422); } $data = $validator->validated(); $data['hashkey'] = hash('sha256', uniqid((string) now(), true)); $data['encoded_by'] = Auth::id(); $entry = BarangayBudget::create($data); return response()->json(['success' => true, 'data' => $entry, 'message' => 'Budget entry recorded']); } public function update(Request $request) { if (!$this->checkWrite()) return ResponseHelper::returnUnauthorized(); $entry = BarangayBudget::where('hashkey', $request->input('target'))->first(); if (!$entry) return ResponseHelper::returnError('Entry not found', 404); $data = $request->only(['source', 'amount', 'description', 'date', 'reference', 'category']); $entry->update($data); return response()->json(['success' => true, 'data' => $entry, 'message' => 'Budget entry updated']); } public function destroy(Request $request) { if (!$this->checkWrite()) return ResponseHelper::returnUnauthorized(); $entry = BarangayBudget::where('hashkey', $request->input('target'))->first(); if (!$entry) return ResponseHelper::returnError('Entry not found', 404); $entry->delete(); return response()->json(['success' => true, 'message' => 'Budget entry deleted']); } public function fiscalYears() { $years = BarangayBudget::distinct()->orderByDesc('fiscal_year')->pluck('fiscal_year'); return response()->json(['success' => true, 'data' => $years]); } }