add projet

This commit is contained in:
root
2026-03-05 12:29:37 -05:00
parent 8d1eef8ba8
commit 23b7db1107
9109 changed files with 1106501 additions and 73 deletions
+382
View File
@@ -0,0 +1,382 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Configuration;
use App\Models\Event;
use App\Models\EventCharges;
use App\Models\Student;
use App\Models\User;
use App\Http\Controllers\Api\InvoiceController;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\Response;
class EventController extends BaseApiController
{
protected Event $event;
protected Configuration $config;
protected EventCharges $eventCharges;
protected Student $student;
protected User $user;
protected InvoiceController $invoiceController;
protected ?string $schoolYear;
protected ?string $semester;
public function __construct()
{
parent::__construct();
$this->event = model(Event::class);
$this->config = model(Configuration::class);
$this->eventCharges = model(EventCharges::class);
$this->student = model(Student::class);
$this->user = model(User::class);
$this->invoiceController = app(InvoiceController::class);
$this->schoolYear = $this->config->getConfig('school_year');
$this->semester = $this->config->getConfig('semester');
}
public function index()
{
$schoolYear = $this->request->getGet('school_year') ?? $this->schoolYear;
$upcomingOnly = $this->request->getGet('upcoming') === 'true';
$query = $this->event->newQuery();
if ($schoolYear) {
$query->where('school_year', $schoolYear);
}
if ($upcomingOnly) {
$today = Carbon::now()->toDateString();
$query->where('expiration_date', '>=', $today);
}
$events = $query->orderBy('created_at', 'DESC')->get()->toArray();
// Count active events
$today = Carbon::now()->toDateString();
$activeEventCount = $this->event->newQuery()
->where('expiration_date', '>=', $today)
->count();
return $this->success([
'events' => $events,
'active_event_count' => $activeEventCount,
], 'Events retrieved successfully');
}
public function show($id = null)
{
$event = $this->event->find($id);
if (!$event) {
return $this->respondError('Event not found', Response::HTTP_NOT_FOUND);
}
return $this->success($event, 'Event retrieved successfully');
}
public function create()
{
$data = $this->payloadData();
if (empty($data)) {
return $this->respondError('Invalid request data', Response::HTTP_BAD_REQUEST);
}
$rules = [
'event_name' => 'required|max_length[255]',
'description' => 'nullable',
'amount' => 'required|numeric',
'expiration_date' => 'required|date',
'semester' => 'nullable',
'school_year' => 'nullable',
];
$errors = $this->validateRequest($data, $rules);
if (!empty($errors)) {
return $this->respondValidationError($errors);
}
$flyerPath = null;
// Handle file upload if present
if ($this->laravelRequest->hasFile('flyer')) {
$file = $this->laravelRequest->file('flyer');
if ($file->isValid()) {
$path = $file->store('event_flyers', 'public');
$flyerPath = $path;
}
}
$payload = [
'event_name' => $data['event_name'],
'description' => $data['description'] ?? null,
'amount' => $data['amount'],
'flyer' => $flyerPath,
'expiration_date' => $data['expiration_date'],
'semester' => $data['semester'] ?? $this->semester,
'school_year' => $data['school_year'] ?? $this->schoolYear,
'created_by' => $this->getCurrentUserId(),
];
try {
$event = $this->event->create($payload);
return $this->respondCreated($event->toArray(), 'Event created successfully');
} catch (\Throwable $e) {
Log::error('Event creation error: ' . $e->getMessage());
return $this->respondError('Failed to create event', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function update($id = null)
{
$event = $this->event->find($id);
if (!$event) {
return $this->respondError('Event not found', Response::HTTP_NOT_FOUND);
}
$data = $this->payloadData();
if (empty($data)) {
return $this->respondError('Invalid request data', Response::HTTP_BAD_REQUEST);
}
$flyerPath = $event['flyer']; // Keep existing flyer by default
// Handle file upload if present
if ($this->laravelRequest->hasFile('flyer')) {
$file = $this->laravelRequest->file('flyer');
if ($file->isValid()) {
// Delete old flyer if exists
if ($flyerPath && Storage::disk('public')->exists($flyerPath)) {
Storage::disk('public')->delete($flyerPath);
}
$path = $file->store('event_flyers', 'public');
$flyerPath = $path;
}
}
$updateData = [];
$allowed = ['event_name', 'description', 'amount', 'expiration_date', 'semester', 'school_year'];
foreach ($allowed as $field) {
if (array_key_exists($field, $data)) {
$updateData[$field] = $data[$field];
}
}
$updateData['flyer'] = $flyerPath;
try {
$this->event->update($id, $updateData);
$updated = $this->event->find($id);
return $this->success($updated->toArray(), 'Event updated successfully');
} catch (\Throwable $e) {
Log::error('Event update error: ' . $e->getMessage());
return $this->respondError('Failed to update event', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function delete($id = null)
{
$event = $this->event->find($id);
if (!$event) {
return $this->respondError('Event not found', Response::HTTP_NOT_FOUND);
}
try {
// Delete related charges and collect parent IDs
$charges = $this->eventCharges->newQuery()
->where('event_id', $id)
->get()
->toArray();
$parentIds = [];
foreach ($charges as $charge) {
$this->eventCharges->delete($charge['id']);
$parentIds[] = $charge['parent_id'];
}
// Delete event
$this->event->delete($id);
$parentIds = array_unique($parentIds);
// Regenerate invoices for affected parents
// Note: generateInvoice method may need to be implemented in InvoiceController
foreach ($parentIds as $parentId) {
// This would need to be implemented or called differently
// $this->invoiceController->generateInvoice($parentId);
}
return $this->success(null, 'Event, charges, and invoices updated successfully');
} catch (\Throwable $e) {
Log::error('Event deletion error: ' . $e->getMessage());
return $this->respondError('Failed to delete event', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* GET /api/v1/events/charges
* Returns event charges with parent and student information
*/
public function charges()
{
$schoolYear = $this->request->getGet('school_year') ?? $this->schoolYear;
$semester = $this->request->getGet('semester') ?? $this->semester;
try {
$parents = $this->user->getParents();
$events = $this->event->getActiveEvents($this->schoolYear);
$charges = $this->eventCharges->newQuery()
->select([
'event_charges.*',
'users.firstname AS parent_firstname',
'users.lastname AS parent_lastname',
'students.firstname AS student_firstname',
'students.lastname AS student_lastname',
'events.event_name'
])
->leftJoin('users', 'users.id', '=', 'event_charges.parent_id')
->leftJoin('students', 'students.id', '=', 'event_charges.student_id')
->leftJoin('events', 'events.id', '=', 'event_charges.event_id')
->where('event_charges.school_year', $schoolYear)
->where('event_charges.semester', $semester)
->orderBy('event_charges.created_at', 'DESC')
->get()
->toArray();
return $this->success([
'charges' => $charges,
'parents' => $parents,
'events' => $events,
'school_year' => $schoolYear,
'semester' => $semester,
], 'Event charges retrieved successfully');
} catch (\Throwable $e) {
Log::error('Event charges retrieval error: ' . $e->getMessage());
return $this->respondError('Failed to retrieve event charges', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* POST /api/v1/events/charges/update
* Updates event charges for a parent and students
*/
public function updateCharges()
{
$data = $this->payloadData();
if (empty($data)) {
return $this->respondError('Invalid request data', Response::HTTP_BAD_REQUEST);
}
$schoolYear = $data['school_year'] ?? $this->schoolYear;
$semester = $data['semester'] ?? $this->semester;
$parentId = $data['parent_id'] ?? null;
$eventId = $data['event_id'] ?? null;
$participations = $data['participation'] ?? [];
if (!$parentId || !$eventId || empty($participations)) {
return $this->respondError('Missing required information: parent_id, event_id, and participation are required', Response::HTTP_BAD_REQUEST);
}
try {
$userId = $this->getCurrentUserId();
$event = $this->event->getEvent($eventId, $schoolYear);
if (!$event) {
return $this->respondError('Event not found', Response::HTTP_NOT_FOUND);
}
foreach ($participations as $studentId => $value) {
$existing = $this->eventCharges->newQuery()
->where('parent_id', $parentId)
->where('student_id', $studentId)
->where('event_id', $eventId)
->where('school_year', $schoolYear)
->where('semester', $semester)
->first();
if ($value === 'no') {
if ($existing) {
$this->eventCharges->delete($existing['id']);
}
continue;
}
// value is 'yes'
$chargeData = [
'parent_id' => $parentId,
'student_id' => $studentId,
'event_id' => $eventId,
'participation' => 'yes',
'charged' => $event['amount'],
'school_year' => $schoolYear,
'semester' => $semester,
];
if ($existing) {
$chargeData['updated_by'] = $userId;
$this->eventCharges->update($existing['id'], $chargeData);
} else {
$chargeData['updated_by'] = $userId;
$this->eventCharges->insert($chargeData);
}
}
// Regenerate invoice for parent
// Note: generateInvoice method may need to be implemented
// $this->invoiceController->generateInvoice($parentId);
return $this->success(null, 'Event charges updated successfully');
} catch (\Throwable $e) {
Log::error('Event charges update error: ' . $e->getMessage());
return $this->respondError('Failed to update event charges', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* GET /api/v1/events/students-with-charges
* Returns students for a parent with their charge status
*/
public function getStudentsWithCharges()
{
$parentId = $this->request->getGet('parent_id');
$semester = $this->request->getGet('semester') ?? $this->semester;
$schoolYear = $this->request->getGet('school_year') ?? $this->schoolYear;
if (!$parentId) {
return $this->respondError('parent_id is required', Response::HTTP_BAD_REQUEST);
}
try {
// Get students for parent
$students = $this->student->newQuery()
->where('parent_id', $parentId)
->get()
->toArray();
// Get student_ids that already have charges
$chargedStudentIds = $this->eventCharges->newQuery()
->where('parent_id', $parentId)
->where('semester', $semester)
->where('school_year', $schoolYear)
->groupBy('student_id')
->pluck('student_id')
->toArray();
$data = [];
foreach ($students as $student) {
$data[] = [
'id' => $student['id'],
'name' => trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? '')),
'charged' => in_array($student['id'], $chargedStudentIds),
];
}
return $this->success($data, 'Students with charges retrieved successfully');
} catch (\Throwable $e) {
Log::error('Get students with charges error: ' . $e->getMessage());
return $this->respondError('Failed to retrieve students with charges', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}