update emergency contact student controller
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user