add class progress and fix endpoints
This commit is contained in:
@@ -41,6 +41,11 @@ class AuthController extends BaseApiController
|
||||
|
||||
$jwtToken = JWTAuth::fromUser($user);
|
||||
$sanctumToken = $user->createToken('api')->plainTextToken;
|
||||
$roles = $user->roles()
|
||||
->where('roles.is_active', 1)
|
||||
->pluck('roles.name')
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $this->respondSuccess([
|
||||
'user' => [
|
||||
@@ -48,6 +53,7 @@ class AuthController extends BaseApiController
|
||||
'firstname' => $user->firstname,
|
||||
'lastname' => $user->lastname,
|
||||
'email' => $user->email,
|
||||
'roles' => $roles,
|
||||
],
|
||||
'jwt' => [
|
||||
'access_token' => $jwtToken,
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\ClassPrep;
|
||||
|
||||
use App\Http\Controllers\Api\BaseApiController;
|
||||
use App\Services\ClassPrep\ClassRosterService;
|
||||
use App\Services\ClassPrep\StickerCountService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ClassPrepController extends BaseApiController
|
||||
{
|
||||
private StickerCountService $stickerCounts;
|
||||
private ClassRosterService $roster;
|
||||
|
||||
public function __construct(StickerCountService $stickerCounts, ClassRosterService $roster)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->stickerCounts = $stickerCounts;
|
||||
$this->roster = $roster;
|
||||
}
|
||||
|
||||
public function stickerCounts(Request $request): JsonResponse
|
||||
{
|
||||
$schoolYear = (string) ($request->query('school_year') ?? '');
|
||||
$semester = (string) ($request->query('semester') ?? '');
|
||||
$classSectionId = $request->query('class_section_id') ?? $request->query('class_id');
|
||||
$classSectionId = is_numeric($classSectionId) ? (int) $classSectionId : null;
|
||||
|
||||
if ($classSectionId !== null && $classSectionId > 0) {
|
||||
$payload = $this->stickerCounts->listForClass($schoolYear, $semester, $classSectionId);
|
||||
} else {
|
||||
$payload = $this->stickerCounts->listAll($schoolYear, $semester);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'data' => $payload,
|
||||
]);
|
||||
}
|
||||
|
||||
public function studentsByClass(Request $request, int $classSectionId): JsonResponse
|
||||
{
|
||||
$schoolYear = (string) ($request->query('school_year') ?? '');
|
||||
|
||||
$students = $this->roster->listStudentsByClass($classSectionId, $schoolYear !== '' ? $schoolYear : null);
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'students' => $students,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,30 @@ use App\Http\Requests\ClassPreparation\ClassPreparationMarkPrintedRequest;
|
||||
use App\Http\Requests\ClassPreparation\ClassPreparationPrintRequest;
|
||||
use App\Http\Resources\ClassPreparation\ClassPreparationPrintResource;
|
||||
use App\Http\Resources\ClassPreparation\ClassPreparationResultResource;
|
||||
use App\Services\ClassPrep\ClassRosterService;
|
||||
use App\Services\ClassPrep\StickerCountService;
|
||||
use App\Services\ClassPreparation\ClassPreparationService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ClassPreparationController extends BaseApiController
|
||||
{
|
||||
private ClassPreparationService $service;
|
||||
private StickerCountService $stickerCounts;
|
||||
private ClassRosterService $roster;
|
||||
|
||||
public function __construct(ClassPreparationService $service)
|
||||
public function __construct(
|
||||
ClassPreparationService $service,
|
||||
StickerCountService $stickerCounts,
|
||||
ClassRosterService $roster
|
||||
)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->service = $service;
|
||||
$this->stickerCounts = $stickerCounts;
|
||||
$this->roster = $roster;
|
||||
}
|
||||
|
||||
public function index(ClassPreparationIndexRequest $request): JsonResponse
|
||||
@@ -93,4 +104,35 @@ class ClassPreparationController extends BaseApiController
|
||||
'print' => new ClassPreparationPrintResource($payload),
|
||||
], 'Class preparation logged.');
|
||||
}
|
||||
|
||||
public function stickerCounts(Request $request): JsonResponse
|
||||
{
|
||||
$schoolYear = (string) ($request->query('school_year') ?? '');
|
||||
$semester = (string) ($request->query('semester') ?? '');
|
||||
$classSectionId = $request->query('class_section_id') ?? $request->query('class_id');
|
||||
$classSectionId = is_numeric($classSectionId) ? (int) $classSectionId : null;
|
||||
|
||||
if ($classSectionId !== null && $classSectionId > 0) {
|
||||
$payload = $this->stickerCounts->listForClass($schoolYear, $semester, $classSectionId);
|
||||
} else {
|
||||
$payload = $this->stickerCounts->listAll($schoolYear, $semester);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'data' => $payload,
|
||||
]);
|
||||
}
|
||||
|
||||
public function studentsByClass(Request $request, int $classSectionId): JsonResponse
|
||||
{
|
||||
$schoolYear = (string) ($request->query('school_year') ?? '');
|
||||
|
||||
$students = $this->roster->listStudentsByClass($classSectionId, $schoolYear !== '' ? $schoolYear : null);
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'students' => $students,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\ClassProgress;
|
||||
|
||||
use App\Http\Controllers\Api\BaseApiController;
|
||||
use App\Http\Requests\ClassProgress\ClassProgressIndexRequest;
|
||||
use App\Http\Requests\ClassProgress\ClassProgressMetaRequest;
|
||||
use App\Http\Requests\ClassProgress\ClassProgressStoreRequest;
|
||||
use App\Http\Requests\ClassProgress\ClassProgressUpdateRequest;
|
||||
use App\Http\Resources\ClassProgress\ClassProgressGroupCollection;
|
||||
use App\Http\Resources\ClassProgress\ClassProgressReportResource;
|
||||
use App\Http\Resources\ClassProgress\ClassProgressShowResource;
|
||||
use App\Models\ClassProgressAttachment;
|
||||
use App\Models\ClassProgressReport;
|
||||
use App\Services\ClassProgress\ClassProgressAttachmentService;
|
||||
use App\Services\ClassProgress\ClassProgressMetaService;
|
||||
use App\Services\ClassProgress\ClassProgressMutationService;
|
||||
use App\Services\ClassProgress\ClassProgressQueryService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class ClassProgressController extends BaseApiController
|
||||
{
|
||||
public function __construct(
|
||||
private ClassProgressQueryService $queryService,
|
||||
private ClassProgressMutationService $mutationService,
|
||||
private ClassProgressMetaService $metaService,
|
||||
private ClassProgressAttachmentService $attachmentService
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->authorizeResource(ClassProgressReport::class, 'class_progress');
|
||||
}
|
||||
|
||||
public function meta(ClassProgressMetaRequest $request): JsonResponse
|
||||
{
|
||||
$classId = $request->validated('class_id');
|
||||
$sundayCount = (int) ($request->validated('sunday_count') ?? 12);
|
||||
|
||||
$payload = [
|
||||
'subject_sections' => $this->metaService->subjectSections(),
|
||||
'status_options' => $this->metaService->statusOptions(),
|
||||
'sunday_options' => $this->metaService->sundayOptions($sundayCount),
|
||||
'curriculum' => $this->metaService->curriculumOptions($classId ? (int) $classId : null),
|
||||
];
|
||||
|
||||
return $this->respondSuccess($payload, 'Progress metadata loaded.');
|
||||
}
|
||||
|
||||
public function index(ClassProgressIndexRequest $request): JsonResponse
|
||||
{
|
||||
$filters = $request->validated();
|
||||
$paginator = $this->queryService->listReports($request->user(), $filters);
|
||||
|
||||
if (!empty($filters['group_by_week'])) {
|
||||
$grouped = ClassProgressGroupCollection::fromPaginator($paginator);
|
||||
return $this->respondSuccess($grouped, 'Progress reports retrieved.');
|
||||
}
|
||||
|
||||
return $this->respondSuccess([
|
||||
'items' => ClassProgressReportResource::collection($paginator->items()),
|
||||
'pagination' => [
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'total' => $paginator->total(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
],
|
||||
], 'Progress reports retrieved.');
|
||||
}
|
||||
|
||||
public function store(ClassProgressStoreRequest $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$filesBySubject = $request->filesBySubject();
|
||||
$reports = $this->mutationService->createReports($request->user(), $request->validated(), $filesBySubject);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $this->respondError($e->getMessage(), 422);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to create class progress reports.', [
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
return $this->respondError('Unable to save progress reports.', 500);
|
||||
}
|
||||
|
||||
return $this->respondCreated(ClassProgressReportResource::collection($reports), 'Progress reports saved.');
|
||||
}
|
||||
|
||||
public function show(ClassProgressReport $class_progress): JsonResponse
|
||||
{
|
||||
$weeklyReports = $this->queryService->weeklyReports($this->laravelRequest->user(), $class_progress);
|
||||
|
||||
return $this->respondSuccess(
|
||||
new ClassProgressShowResource([
|
||||
'report' => $class_progress,
|
||||
'weekly_reports' => $weeklyReports,
|
||||
'status_options' => $this->metaService->statusOptions(),
|
||||
]),
|
||||
'Progress report retrieved.'
|
||||
);
|
||||
}
|
||||
|
||||
public function update(ClassProgressUpdateRequest $request, ClassProgressReport $class_progress): JsonResponse
|
||||
{
|
||||
try {
|
||||
$updated = $this->mutationService->updateReport($class_progress, $request->validated(), $request->attachments());
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $this->respondError($e->getMessage(), 422);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to update class progress report.', [
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
return $this->respondError('Unable to update progress report.', 500);
|
||||
}
|
||||
|
||||
return $this->respondSuccess(new ClassProgressReportResource($updated), 'Progress report updated.');
|
||||
}
|
||||
|
||||
public function destroy(ClassProgressReport $class_progress): JsonResponse
|
||||
{
|
||||
try {
|
||||
$this->mutationService->deleteReport($class_progress);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to delete class progress report.', [
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
return $this->respondError('Unable to delete progress report.', 500);
|
||||
}
|
||||
|
||||
return $this->respondDeleted(null, 'Progress report deleted.');
|
||||
}
|
||||
|
||||
public function downloadAttachment(int $attachment): BinaryFileResponse|JsonResponse
|
||||
{
|
||||
$record = ClassProgressAttachment::query()->find($attachment);
|
||||
if (!$record || !$record->file_path) {
|
||||
return $this->respondError('Attachment not found.', 404);
|
||||
}
|
||||
|
||||
if ($record->report) {
|
||||
$this->authorize('view', $record->report);
|
||||
}
|
||||
|
||||
$path = $this->attachmentService->resolvePath($record->file_path);
|
||||
if (!$path) {
|
||||
return $this->respondError('Attachment missing.', 404);
|
||||
}
|
||||
|
||||
$downloadName = $record->original_name ?: basename($path);
|
||||
return response()->download($path, $downloadName);
|
||||
}
|
||||
|
||||
public function downloadLegacyAttachment(ClassProgressReport $class_progress): BinaryFileResponse|JsonResponse
|
||||
{
|
||||
$this->authorize('view', $class_progress);
|
||||
|
||||
if (!$class_progress->attachment_path) {
|
||||
return $this->respondError('Attachment not found.', 404);
|
||||
}
|
||||
|
||||
$path = $this->attachmentService->resolvePath($class_progress->attachment_path);
|
||||
if (!$path) {
|
||||
return $this->respondError('Attachment missing.', 404);
|
||||
}
|
||||
|
||||
return response()->download($path, basename($path));
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,9 @@ class StudentController extends BaseApiController
|
||||
$data = array_merge($request->query->all(), $request->all(), $request->json()->all());
|
||||
$validator = Validator::make($data, [
|
||||
'school_year' => ['nullable', 'string', 'max:50'],
|
||||
'parent_id' => ['nullable', 'integer', 'min:1'],
|
||||
'parent_ids' => ['nullable', 'array'],
|
||||
'parent_ids.*' => ['integer', 'min:1'],
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@@ -77,7 +80,16 @@ class StudentController extends BaseApiController
|
||||
}
|
||||
|
||||
$payload = $validator->validated();
|
||||
$data = $this->directoryService->listStudents($payload['school_year'] ?? null);
|
||||
$parentIds = [];
|
||||
if (!empty($payload['parent_ids'])) {
|
||||
$parentIds = array_values(array_unique(array_map('intval', $payload['parent_ids'])));
|
||||
}
|
||||
if (!empty($payload['parent_id'])) {
|
||||
$parentIds[] = (int) $payload['parent_id'];
|
||||
}
|
||||
$parentIds = array_values(array_unique(array_filter($parentIds)));
|
||||
|
||||
$data = $this->directoryService->listStudents($payload['school_year'] ?? null, $parentIds ?: null);
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
|
||||
Reference in New Issue
Block a user