362 lines
12 KiB
PHP
362 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use App\Models\StudentType;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Password;
|
|
use App\Models\StudentProfile;
|
|
use App\Models\BillingAccount;
|
|
use App\Models\ParentProfile;
|
|
|
|
class StudentController extends Controller
|
|
{
|
|
|
|
|
|
|
|
public function index()
|
|
{
|
|
$students = StudentProfile::with(['user', 'billingAccount'])->get();
|
|
|
|
return view('admin.students.index', compact('students'));
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$parents = ParentProfile::with('user')->get();
|
|
$studentTypes = StudentType::all();
|
|
|
|
return view('admin.students.create', compact('parents', 'studentTypes'));
|
|
}
|
|
|
|
public function edit(StudentProfile $student)
|
|
{
|
|
$student->load(['user', 'billingAccount', 'billingAccount.primaryParent']);
|
|
|
|
$parents = ParentProfile::with('user')->get();
|
|
$studentTypes = StudentType::all();
|
|
|
|
return view('admin.students.edit', compact('student', 'parents', 'studentTypes'));
|
|
}
|
|
|
|
public function update(Request $request, StudentProfile $student)
|
|
{
|
|
$validated = $request->validate([
|
|
// Student
|
|
'student_first_name' => 'required|string|max:255',
|
|
'student_last_name' => 'required|string|max:255',
|
|
'student_phone' => 'nullable|string|max:255',
|
|
// If you allow changing student email:
|
|
// 'student_email' => ['required','email', Rule::unique('users','email')->ignore($student->user_id)],
|
|
|
|
'date_of_birth' => 'nullable|date',
|
|
'student_type_id' => 'required|exists:student_types,id',
|
|
|
|
// Parent selection
|
|
'parent_option' => 'required|in:none,existing,new',
|
|
'existing_parent_id' => 'required_if:parent_option,existing|nullable|exists:parent_profiles,id',
|
|
|
|
// New parent (only used if parent_option=new)
|
|
'parent_first_name' => 'required_if:parent_option,new|nullable|string|max:255',
|
|
'parent_last_name' => 'required_if:parent_option,new|nullable|string|max:255',
|
|
'parent_email' => 'required_if:parent_option,new|nullable|email|unique:users,email',
|
|
'parent_phone' => 'nullable|string|max:255',
|
|
|
|
// Billing (match your edit form; keep minimal initially)
|
|
'billing_account_id' => 'sometimes|nullable|exists:billing_accounts,id',
|
|
'billing_name' => 'required|string|max:255',
|
|
'invoice_email' => 'required|email',
|
|
'billing_phone' => 'nullable|string|max:255',
|
|
'contact_name' => 'nullable|string|max:255',
|
|
'address_line1' => 'required|string|max:255',
|
|
'address_line2' => 'nullable|string|max:255',
|
|
'town' => 'required|string|max:255',
|
|
'postcode' => 'required|string|max:50',
|
|
'country' => 'required|string|max:255',
|
|
]);
|
|
|
|
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
// Load student user
|
|
$student->load('user');
|
|
|
|
// 1) Update STUDENT USER
|
|
$student->user->update([
|
|
'first_name' => $validated['student_first_name'],
|
|
'last_name' => $validated['student_last_name'],
|
|
'phone' => $validated['student_phone'] ?? null,
|
|
// 'email' => $validated['student_email'],
|
|
]);
|
|
|
|
// 2) Update STUDENT PROFILE
|
|
$student->update([
|
|
'date_of_birth' => $validated['date_of_birth'] ?? null,
|
|
'student_type_id' => $validated['student_type_id'],
|
|
// billing_account_id handled below
|
|
]);
|
|
|
|
// 3) Resolve parent user based on parent_option
|
|
$parentProfile = null;
|
|
|
|
if ($validated['parent_option'] === 'existing') {
|
|
$parentProfile = ParentProfile::with('user')->find($validated['existing_parent_id']);
|
|
}
|
|
|
|
if ($validated['parent_option'] === 'new') {
|
|
$parentUser = User::create([
|
|
'first_name' => $validated['parent_first_name'],
|
|
'last_name' => $validated['parent_last_name'],
|
|
'email' => $validated['parent_email'],
|
|
'phone' => $validated['parent_phone'],
|
|
'password' => Hash::make(str()->random(16)),
|
|
]);
|
|
|
|
$parentUser->assignRole('parent');
|
|
|
|
$parentProfile = ParentProfile::firstOrCreate(
|
|
['user_id' => $parentUser->id],
|
|
['phone' => $parentUser->phone]
|
|
);
|
|
|
|
// ensure $parentProfile has user loaded for later
|
|
$parentProfile->load('user');
|
|
}
|
|
|
|
if ($parentProfile && $parentProfile->user) {
|
|
// ensure role even for the "existing" case
|
|
$parentProfile->user->assignRole('parent');
|
|
}
|
|
|
|
// 4) Billing account: update existing or create new (same logic as store)
|
|
if (!empty($validated['billing_account_id'])) {
|
|
$billingAccount = BillingAccount::findOrFail($validated['billing_account_id']);
|
|
$billingAccount->update([
|
|
'name' => $validated['billing_name'],
|
|
'contact_name' => $validated['contact_name'],
|
|
'invoice_email' => $validated['invoice_email'],
|
|
'phone' => $validated['billing_phone'],
|
|
'address_line1' => $validated['address_line1'],
|
|
'address_line2' => $validated['address_line2'],
|
|
'town' => $validated['town'],
|
|
'postcode' => $validated['postcode'],
|
|
'country' => $validated['country'],
|
|
'primary_parent_user_id' => $parentProfile?->user_id,
|
|
]);
|
|
} else {
|
|
$billingAccount = BillingAccount::create([
|
|
'name' => $validated['billing_name'],
|
|
'contact_name' => $validated['contact_name'],
|
|
'invoice_email' => $validated['invoice_email'],
|
|
'phone' => $validated['billing_phone'],
|
|
'address_line1' => $validated['address_line1'],
|
|
'address_line2' => $validated['address_line2'],
|
|
'town' => $validated['town'],
|
|
'postcode' => $validated['postcode'],
|
|
'country' => $validated['country'],
|
|
'primary_parent_user_id' => $parentProfile?->user_id,
|
|
]);
|
|
}
|
|
|
|
if ($validated['parent_option'] === 'none') {
|
|
$billingAccount->update(['primary_parent_user_id' => null]);
|
|
}
|
|
|
|
// Ensure student profile points at the billing account we just resolved
|
|
$student->billing_account_id = $billingAccount->id;
|
|
$student->save();
|
|
|
|
// 5) Parent pivot handling
|
|
if ($validated['parent_option'] === 'none') {
|
|
$student->parents()->detach();
|
|
} else {
|
|
if ($parentProfile) {
|
|
// ONE parent only:
|
|
$student->parents()->sync([
|
|
$parentProfile->id => [
|
|
'relationship' => null,
|
|
'notes' => null,
|
|
],
|
|
]);
|
|
}
|
|
}
|
|
|
|
DB::commit();
|
|
|
|
return redirect()
|
|
->route('admin.students.edit', $student->id)
|
|
->with('success', 'Student updated successfully.');
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
// -----------------------------
|
|
// Validation
|
|
// -----------------------------
|
|
$validated = $request->validate([
|
|
// Student
|
|
'student_first_name' => 'required|string|max:255',
|
|
'student_last_name' => 'required|string|max:255',
|
|
'student_email' => 'required|email|unique:users,email',
|
|
'student_phone' => 'nullable|string|max:255',
|
|
'date_of_birth' => 'nullable|date',
|
|
'student_type_id' => 'required|exists:student_types,id',
|
|
|
|
// Parent selection
|
|
'parent_option' => 'required|in:none,existing,new',
|
|
'existing_parent_id' => 'required_if:parent_option,existing|nullable|exists:parent_profiles,id',
|
|
|
|
// New parent
|
|
'parent_first_name' => 'nullable|string|max:255',
|
|
'parent_last_name' => 'nullable|string|max:255',
|
|
'parent_email' => 'nullable|email|unique:users,email',
|
|
'parent_phone' => 'nullable|string|max:255',
|
|
|
|
// Billing
|
|
'billing_account_id' => 'sometimes|nullable|exists:billing_accounts,id',
|
|
'billing_name' => 'required|string|max:255',
|
|
'invoice_email' => 'required|email',
|
|
'billing_phone' => 'nullable|string|max:255',
|
|
'contact_name' => 'nullable|string|max:255',
|
|
'address_line1' => 'required|string|max:255',
|
|
'address_line2' => 'nullable|string|max:255',
|
|
'town' => 'required|string|max:255',
|
|
'postcode' => 'required|string|max:50',
|
|
'country' => 'required|string|max:255',
|
|
]);
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
|
|
// ===============================================================
|
|
// 1) Create STUDENT USER
|
|
// ===============================================================
|
|
$studentUser = User::create([
|
|
'first_name' => $validated['student_first_name'],
|
|
'last_name' => $validated['student_last_name'],
|
|
'email' => $validated['student_email'],
|
|
'phone' => $validated['student_phone'],
|
|
'password' => Hash::make(str()->random(16)), // Temporary password
|
|
]);
|
|
|
|
$studentUser->assignRole('student');
|
|
|
|
|
|
// ===============================================================
|
|
// 2) Handle PARENT selection
|
|
// ===============================================================
|
|
|
|
$parentProfile = null;
|
|
|
|
if ($validated['parent_option'] === 'existing') {
|
|
$parentProfile = ParentProfile::find($validated['existing_parent_id']);
|
|
}
|
|
|
|
if ($validated['parent_option'] === 'new') {
|
|
create([
|
|
'first_name' => $validated['parent_first_name'],
|
|
'last_name' => $validated['parent_last_name'],
|
|
'email' => $validated['parent_email'],
|
|
'phone' => $validated['parent_phone'],
|
|
'password' => Hash::make(str()->random(16)),
|
|
]);
|
|
$parentUser->assignRole('parent');
|
|
|
|
$parentProfile = ParentProfile::firstOrCreate(
|
|
['user_id' => $parentUser->id],
|
|
['phone' => $parentUser->phone]
|
|
);
|
|
}
|
|
|
|
if ($parentProfile) {
|
|
$parentProfile->user?->assignRole('parent');
|
|
}
|
|
|
|
// Note: If parent_option == 'none', $parentUser remains null.
|
|
|
|
|
|
// ===============================================================
|
|
// 3) Create BILLING ACCOUNT
|
|
// ===============================================================
|
|
if (!empty($validated['billing_account_id'])) {
|
|
// Use existing billing account
|
|
$billingAccount = BillingAccount::find($validated['billing_account_id']);
|
|
} else {
|
|
$billingAccount = BillingAccount::create([
|
|
'name' => $validated['billing_name'],
|
|
'contact_name' => $validated['contact_name'],
|
|
'invoice_email' => $validated['invoice_email'],
|
|
'phone' => $validated['billing_phone'],
|
|
'address_line1' => $validated['address_line1'],
|
|
'address_line2' => $validated['address_line2'],
|
|
'town' => $validated['town'],
|
|
'postcode' => $validated['postcode'],
|
|
'country' => $validated['country'],
|
|
'primary_parent_user_id' => $parentProfile?->user_id,
|
|
]);
|
|
}
|
|
|
|
// ===============================================================
|
|
// 4) Create STUDENT PROFILE
|
|
// ===============================================================
|
|
$studentProfile = StudentProfile::create([
|
|
'user_id' => $studentUser->id,
|
|
'date_of_birth' => $validated['date_of_birth'] ?? null,
|
|
'billing_account_id' => $billingAccount->id,
|
|
'student_type_id' => $validated['student_type_id'],
|
|
]);
|
|
|
|
// ===============================================================
|
|
// 4B) Create/link PARENT PROFILE + pivot relationship
|
|
// ===============================================================
|
|
if ($parentUser) {
|
|
|
|
// Ensure parent has role (covers "existing parent" case)
|
|
$parentUser->assignRole('parent');
|
|
|
|
// Ensure parent profile exists
|
|
$parentProfile = ParentProfile::firstOrCreate(
|
|
['user_id' => $parentUser->id],
|
|
['phone' => $parentUser->phone] // optional default
|
|
);
|
|
|
|
// Link parent profile to student profile via pivot
|
|
$studentProfile->parents()->syncWithoutDetaching([
|
|
$parentProfile->id => [
|
|
'relationship' => null,
|
|
'notes' => null,
|
|
],
|
|
]);
|
|
}
|
|
|
|
// ===============================================================
|
|
// 5) Send password setup email to student user
|
|
// ===============================================================
|
|
Password::sendResetLink(['email' => $studentUser->email]);
|
|
|
|
|
|
DB::commit();
|
|
|
|
return redirect()
|
|
->route('admin.students.index')
|
|
->with('success', 'Student created successfully.');
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
throw $e; // (You can customise error messages later)
|
|
}
|
|
}
|
|
}
|