update emergency contact student controller

This commit is contained in:
root
2026-03-25 17:59:40 -04:00
parent 33be0c9a0d
commit c582bfc242
11 changed files with 179 additions and 16 deletions
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api\Administrator;
use App\Http\Controllers\Controller;
use App\Http\Requests\EmergencyContacts\EmergencyContactParentRequest;
use App\Http\Requests\EmergencyContacts\EmergencyContactUpdateRequest;
use App\Http\Resources\EmergencyContacts\EmergencyContactGroupResource;
use App\Http\Resources\EmergencyContacts\EmergencyContactResource;
@@ -28,9 +29,10 @@ class EmergencyContactController extends Controller
]);
}
public function update(EmergencyContactUpdateRequest $request, int $contactId): JsonResponse
public function show(EmergencyContactParentRequest $request, int $contactId): JsonResponse
{
$contact = $this->crudService->update($contactId, $request->validated());
$parentId = (int) $request->validated()['parent_id'];
$contact = $this->crudService->findForParent($contactId, $parentId);
return response()->json([
'ok' => true,
@@ -38,9 +40,21 @@ class EmergencyContactController extends Controller
]);
}
public function destroy(int $contactId): JsonResponse
public function update(EmergencyContactUpdateRequest $request, int $contactId): JsonResponse
{
$this->crudService->delete($contactId);
$payload = $request->validated();
$contact = $this->crudService->update($contactId, (int) $payload['parent_id'], $payload);
return response()->json([
'ok' => true,
'contact' => new EmergencyContactResource($contact),
]);
}
public function destroy(EmergencyContactParentRequest $request, int $contactId): JsonResponse
{
$parentId = (int) $request->validated()['parent_id'];
$this->crudService->delete($contactId, $parentId);
return response()->json(['ok' => true]);
}
@@ -58,4 +58,17 @@ class ConfigurationAdminController extends BaseApiController
return response()->json(['ok' => true]);
}
public function getByKey(string $configKey): JsonResponse
{
$config = $this->service->getByKey($configKey);
if (!$config) {
return response()->json(['ok' => false, 'message' => 'Configuration not found.'], 404);
}
return response()->json([
'ok' => true,
'config' => new ConfigurationResource($config->toArray()),
]);
}
}
@@ -123,7 +123,6 @@ class StudentController extends BaseApiController
'parent_id',
'registration_date',
'tuition_paid',
'rfid_tag',
'semester',
'year_of_registration',
'school_year',
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Requests\EmergencyContacts;
use App\Http\Requests\ApiFormRequest;
class EmergencyContactParentRequest extends ApiFormRequest
{
public function rules(): array
{
return [
'parent_id' => ['required', 'integer', 'min:1'],
];
}
}
@@ -9,6 +9,7 @@ class EmergencyContactUpdateRequest extends ApiFormRequest
public function rules(): array
{
return [
'parent_id' => ['required', 'integer', 'min:1'],
'name' => ['required', 'string', 'max:150'],
'cellphone' => ['required', 'string', 'max:30'],
'email' => ['nullable', 'email', 'max:150'],
@@ -12,9 +12,22 @@ class EmergencyContactCrudService
) {
}
public function update(int $contactId, array $payload): array
public function findForParent(int $contactId, int $parentId): array
{
$contact = EmergencyContact::query()->findOrFail($contactId);
$contact = EmergencyContact::query()
->where('id', $contactId)
->where('parent_id', $parentId)
->firstOrFail();
return $contact->toArray();
}
public function update(int $contactId, int $parentId, array $payload): array
{
$contact = EmergencyContact::query()
->where('id', $contactId)
->where('parent_id', $parentId)
->firstOrFail();
$contact->update([
'emergency_contact_name' => $payload['name'],
@@ -26,9 +39,13 @@ class EmergencyContactCrudService
return $contact->toArray();
}
public function delete(int $contactId): void
public function delete(int $contactId, int $parentId): void
{
$contact = EmergencyContact::query()->findOrFail($contactId);
$contact = EmergencyContact::query()
->where('id', $contactId)
->where('parent_id', $parentId)
->firstOrFail();
$contact->delete();
}
}
@@ -46,4 +46,12 @@ class ConfigurationService
return (bool) $config->delete();
}
public function getByKey(string $key): ?Configuration
{
return Configuration::query()
->where('config_key', $key)
->orderByDesc('id')
->first();
}
}
@@ -183,7 +183,6 @@ class StudentDirectoryService
'parent_id',
'registration_date',
'tuition_paid',
'rfid_tag',
'semester',
'year_of_registration',
'school_year',
+1 -1
View File
@@ -168,7 +168,7 @@ This document lists every API controller alphabetically with any inline route co
- `POST /api/v1/communications/send-email` (`sendEmail`) Body requires `student_id`, `family_id`, `template_key`, `subject`, `body`, and `recipients` (JSON array or string). Accepts optional `cc`/`bcc`, sends the HTML email through `Mail::send`, and logs the result in `communication_logs`.
## ConfigurationController
**File:** `app/Http/Controllers/Api/ConfigurationController.php`
**File:** `app/Http/Controllers/Api/Settings/ConfigurationAdminController.php`
**Purpose:** Manage key/value pairs stored in the `configuration` table.
- `GET /api/v1/configuration` (`index`) Paginated list ordered by ID with optional fuzzy `key` search.
+2
View File
@@ -207,6 +207,7 @@ Route::prefix('v1')->group(function () {
Route::get('emergency-contacts', [AdministratorEmergencyContactController::class, 'index']);
Route::get('emergency-contacts/data', [AdministratorEmergencyContactController::class, 'index']);
Route::get('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'show']);
Route::patch('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'update']);
Route::delete('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'destroy']);
});
@@ -706,6 +707,7 @@ Route::prefix('v1')->group(function () {
Route::prefix('configuration')->group(function () {
Route::get('/', [ConfigurationAdminController::class, 'index']);
Route::get('key/{config_key}', [ConfigurationAdminController::class, 'getByKey']);
Route::post('/', [ConfigurationAdminController::class, 'store']);
Route::patch('{id}', [ConfigurationAdminController::class, 'update']);
Route::delete('{id}', [ConfigurationAdminController::class, 'destroy']);
@@ -54,7 +54,7 @@ class EmergencyContactControllerTest extends TestCase
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin);
Sanctum::actingAs($admin, [], 'api');
$response = $this->getJson('/api/v1/administrator/emergency-contacts');
$response->assertOk();
@@ -79,12 +79,15 @@ class EmergencyContactControllerTest extends TestCase
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin);
$response = $this->patchJson('/api/v1/administrator/emergency-contacts/' . $contact->id, [
Sanctum::actingAs($admin, [], 'api');
$response = $this->patch('/api/v1/administrator/emergency-contacts/' . $contact->id, [
'parent_id' => $parent->id,
'name' => 'New Name',
'cellphone' => '5555555555',
'email' => 'new@example.com',
'relation' => 'Neighbor',
], [
'Accept' => 'application/json',
]);
$response->assertOk();
@@ -112,8 +115,12 @@ class EmergencyContactControllerTest extends TestCase
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin);
$response = $this->deleteJson('/api/v1/administrator/emergency-contacts/' . $contact->id);
Sanctum::actingAs($admin, [], 'api');
$response = $this->delete('/api/v1/administrator/emergency-contacts/' . $contact->id, [
'parent_id' => $parent->id,
], [
'Accept' => 'application/json',
]);
$response->assertOk();
$response->assertJson(['ok' => true]);
@@ -121,4 +128,92 @@ class EmergencyContactControllerTest extends TestCase
'id' => $contact->id,
]);
}
public function test_show_returns_single_contact_for_parent(): void
{
$admin = User::factory()->create();
$parent = User::factory()->create();
$contact = EmergencyContact::query()->create([
'parent_id' => $parent->id,
'emergency_contact_name' => 'Single Contact',
'cellphone' => '7777777777',
'email' => 'single@example.com',
'relation' => 'Friend',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin, [], 'api');
$response = $this->get('/api/v1/administrator/emergency-contacts/' . $contact->id . '?parent_id=' . $parent->id, [
'Accept' => 'application/json',
]);
$response->assertOk();
$response->assertJsonPath('contact.id', $contact->id);
$response->assertJsonPath('contact.parent_id', $parent->id);
}
public function test_update_requires_matching_parent_id(): void
{
$admin = User::factory()->create();
$parent = User::factory()->create();
$otherParent = User::factory()->create();
$contact = EmergencyContact::query()->create([
'parent_id' => $parent->id,
'emergency_contact_name' => 'Old Name',
'cellphone' => '8888888888',
'email' => 'old@example.com',
'relation' => 'Friend',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin, [], 'api');
$response = $this->patch('/api/v1/administrator/emergency-contacts/' . $contact->id, [
'parent_id' => $otherParent->id,
'name' => 'New Name',
'cellphone' => '9999999999',
'email' => 'new@example.com',
'relation' => 'Neighbor',
], [
'Accept' => 'application/json',
]);
$response->assertNotFound();
$this->assertDatabaseHas('emergency_contacts', [
'id' => $contact->id,
'emergency_contact_name' => 'Old Name',
]);
}
public function test_destroy_requires_matching_parent_id(): void
{
$admin = User::factory()->create();
$parent = User::factory()->create();
$otherParent = User::factory()->create();
$contact = EmergencyContact::query()->create([
'parent_id' => $parent->id,
'emergency_contact_name' => 'Delete Name',
'cellphone' => '1010101010',
'email' => 'delete@example.com',
'relation' => 'Friend',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
Sanctum::actingAs($admin, [], 'api');
$response = $this->delete('/api/v1/administrator/emergency-contacts/' . $contact->id, [
'parent_id' => $otherParent->id,
], [
'Accept' => 'application/json',
]);
$response->assertNotFound();
$this->assertDatabaseHas('emergency_contacts', [
'id' => $contact->id,
]);
}
}