feat: implement barangay system phases 2-14
Some checks failed
tests / PHP 8.2 (swoole-5.1.6) (push) Has been cancelled
tests / PHP 8.3 (swoole-5.1.6) (push) Has been cancelled
tests / PHP 8.4 (swoole-6.0) (push) Has been cancelled

Complete adaptation from BukidBountyApp to Philippine barangay governance:

- Barangay models: Resident, Household, HouseholdMember, Blotter, BlotterHearing,
  DocumentRequest, RequestPayment, RequestType, BarangayProject, BarangayBudget
- Controllers: ResidentController, HouseholdController, BlotterController,
  BlotterHearingController, DocumentRequestController, RequestTypeController,
  ProjectController, BudgetController, QRPHController, AdminConsoleController,
  UserController, FileController, ChapterController, LoginController
- Vue pages: Home, ManageResidents, ResidentProfile, ManageHouseholds, ManageBlotters,
  BlotterDetail, RequestDocument, ManageDocumentRequests, DocumentRequestDetail,
  ManageRequestTypes, ManageProjects, BudgetLedger, AdminConsole
- Barangay roles: PunongBarangay, Kagawad, Secretary, Treasurer, SK, Tanod, BHW, Staff, Resident
- UserPermissions matrix rewritten with barangay-specific permission mappings
- VueRouteMap replaced with barangay SPA routes
- UserActions enum references corrected across all controllers
- Removed all market/cooperative/POS/subscription code and models
This commit is contained in:
Jonathan Sykes
2026-06-07 03:09:09 +08:00
parent 19fec0933b
commit fbb7e3ff37
234 changed files with 5582 additions and 39457 deletions

View File

@@ -0,0 +1,126 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Barangay;
use App\Enums\UserActions;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\Barangay\BarangayBudget;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hypervel\Support\Facades\Validator;
class BudgetController
{
private function checkRead(): bool
{
return UserPermissions::isActionPermitted(Auth::user()->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]);
}
}