update emergency contact student controller
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Api\Administrator;
|
namespace App\Http\Controllers\Api\Administrator;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\EmergencyContacts\EmergencyContactParentRequest;
|
||||||
use App\Http\Requests\EmergencyContacts\EmergencyContactUpdateRequest;
|
use App\Http\Requests\EmergencyContacts\EmergencyContactUpdateRequest;
|
||||||
use App\Http\Resources\EmergencyContacts\EmergencyContactGroupResource;
|
use App\Http\Resources\EmergencyContacts\EmergencyContactGroupResource;
|
||||||
use App\Http\Resources\EmergencyContacts\EmergencyContactResource;
|
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([
|
return response()->json([
|
||||||
'ok' => true,
|
'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]);
|
return response()->json(['ok' => true]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,4 +58,17 @@ class ConfigurationAdminController extends BaseApiController
|
|||||||
|
|
||||||
return response()->json(['ok' => true]);
|
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',
|
'parent_id',
|
||||||
'registration_date',
|
'registration_date',
|
||||||
'tuition_paid',
|
'tuition_paid',
|
||||||
'rfid_tag',
|
|
||||||
'semester',
|
'semester',
|
||||||
'year_of_registration',
|
'year_of_registration',
|
||||||
'school_year',
|
'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
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'parent_id' => ['required', 'integer', 'min:1'],
|
||||||
'name' => ['required', 'string', 'max:150'],
|
'name' => ['required', 'string', 'max:150'],
|
||||||
'cellphone' => ['required', 'string', 'max:30'],
|
'cellphone' => ['required', 'string', 'max:30'],
|
||||||
'email' => ['nullable', 'email', 'max:150'],
|
'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([
|
$contact->update([
|
||||||
'emergency_contact_name' => $payload['name'],
|
'emergency_contact_name' => $payload['name'],
|
||||||
@@ -26,9 +39,13 @@ class EmergencyContactCrudService
|
|||||||
return $contact->toArray();
|
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();
|
$contact->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,12 @@ class ConfigurationService
|
|||||||
|
|
||||||
return (bool) $config->delete();
|
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',
|
'parent_id',
|
||||||
'registration_date',
|
'registration_date',
|
||||||
'tuition_paid',
|
'tuition_paid',
|
||||||
'rfid_tag',
|
|
||||||
'semester',
|
'semester',
|
||||||
'year_of_registration',
|
'year_of_registration',
|
||||||
'school_year',
|
'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`.
|
- `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
|
## 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.
|
**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.
|
- `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', [AdministratorEmergencyContactController::class, 'index']);
|
||||||
Route::get('emergency-contacts/data', [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::patch('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'update']);
|
||||||
Route::delete('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'destroy']);
|
Route::delete('emergency-contacts/{contactId}', [AdministratorEmergencyContactController::class, 'destroy']);
|
||||||
});
|
});
|
||||||
@@ -706,6 +707,7 @@ Route::prefix('v1')->group(function () {
|
|||||||
|
|
||||||
Route::prefix('configuration')->group(function () {
|
Route::prefix('configuration')->group(function () {
|
||||||
Route::get('/', [ConfigurationAdminController::class, 'index']);
|
Route::get('/', [ConfigurationAdminController::class, 'index']);
|
||||||
|
Route::get('key/{config_key}', [ConfigurationAdminController::class, 'getByKey']);
|
||||||
Route::post('/', [ConfigurationAdminController::class, 'store']);
|
Route::post('/', [ConfigurationAdminController::class, 'store']);
|
||||||
Route::patch('{id}', [ConfigurationAdminController::class, 'update']);
|
Route::patch('{id}', [ConfigurationAdminController::class, 'update']);
|
||||||
Route::delete('{id}', [ConfigurationAdminController::class, 'destroy']);
|
Route::delete('{id}', [ConfigurationAdminController::class, 'destroy']);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class EmergencyContactControllerTest extends TestCase
|
|||||||
'school_year' => '2025-2026',
|
'school_year' => '2025-2026',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Sanctum::actingAs($admin);
|
Sanctum::actingAs($admin, [], 'api');
|
||||||
$response = $this->getJson('/api/v1/administrator/emergency-contacts');
|
$response = $this->getJson('/api/v1/administrator/emergency-contacts');
|
||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
@@ -79,12 +79,15 @@ class EmergencyContactControllerTest extends TestCase
|
|||||||
'school_year' => '2025-2026',
|
'school_year' => '2025-2026',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Sanctum::actingAs($admin);
|
Sanctum::actingAs($admin, [], 'api');
|
||||||
$response = $this->patchJson('/api/v1/administrator/emergency-contacts/' . $contact->id, [
|
$response = $this->patch('/api/v1/administrator/emergency-contacts/' . $contact->id, [
|
||||||
|
'parent_id' => $parent->id,
|
||||||
'name' => 'New Name',
|
'name' => 'New Name',
|
||||||
'cellphone' => '5555555555',
|
'cellphone' => '5555555555',
|
||||||
'email' => 'new@example.com',
|
'email' => 'new@example.com',
|
||||||
'relation' => 'Neighbor',
|
'relation' => 'Neighbor',
|
||||||
|
], [
|
||||||
|
'Accept' => 'application/json',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
@@ -112,8 +115,12 @@ class EmergencyContactControllerTest extends TestCase
|
|||||||
'school_year' => '2025-2026',
|
'school_year' => '2025-2026',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Sanctum::actingAs($admin);
|
Sanctum::actingAs($admin, [], 'api');
|
||||||
$response = $this->deleteJson('/api/v1/administrator/emergency-contacts/' . $contact->id);
|
$response = $this->delete('/api/v1/administrator/emergency-contacts/' . $contact->id, [
|
||||||
|
'parent_id' => $parent->id,
|
||||||
|
], [
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
]);
|
||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
$response->assertJson(['ok' => true]);
|
$response->assertJson(['ok' => true]);
|
||||||
@@ -121,4 +128,92 @@ class EmergencyContactControllerTest extends TestCase
|
|||||||
'id' => $contact->id,
|
'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