fix apply the plan docs/alrahma_api_fix_plan_school_year_only_v7
API CI/CD / Validate (composer + pint) (push) Successful in 3m10s
API CI/CD / Test (PHPUnit) (push) Failing after 6m49s
API CI/CD / Build frontend assets (push) Successful in 1m3s
API CI/CD / Security audit (push) Failing after 1m0s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
API CI/CD / Validate (composer + pint) (push) Successful in 3m10s
API CI/CD / Test (PHPUnit) (push) Failing after 6m49s
API CI/CD / Build frontend assets (push) Successful in 1m3s
API CI/CD / Security audit (push) Failing after 1m0s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Families;
|
||||
|
||||
use App\Models\StudentClass;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ParentProfileAdminQueryService
|
||||
{
|
||||
public function __construct(private FamilyFinanceService $finance) {}
|
||||
|
||||
public function index(string $schoolYear, string $search = '', int $perPage = 25): LengthAwarePaginator
|
||||
{
|
||||
$query = DB::table('users as u')
|
||||
->select(
|
||||
'u.id',
|
||||
'u.firstname',
|
||||
'u.lastname',
|
||||
'u.email',
|
||||
'u.cellphone',
|
||||
'u.status',
|
||||
DB::raw('COUNT(DISTINCT fg.family_id) as families_count'),
|
||||
DB::raw('COUNT(DISTINCT s.id) as selected_year_students_count'),
|
||||
DB::raw('COALESCE(SUM(DISTINCT i.balance), 0) as balance')
|
||||
)
|
||||
->leftJoin('family_guardians as fg', 'fg.user_id', '=', 'u.id')
|
||||
->leftJoin('family_students as fs', 'fs.family_id', '=', 'fg.family_id')
|
||||
->leftJoin('students as s', function ($join) use ($schoolYear) {
|
||||
$join->on('s.id', '=', 'fs.student_id')
|
||||
->where('s.school_year', '=', $schoolYear);
|
||||
})
|
||||
->leftJoin('invoices as i', function ($join) use ($schoolYear) {
|
||||
$join->on('i.parent_id', '=', 'u.id')
|
||||
->where('i.school_year', '=', $schoolYear);
|
||||
})
|
||||
->where($this->relevantParentConstraint($schoolYear))
|
||||
->groupBy('u.id', 'u.firstname', 'u.lastname', 'u.email', 'u.cellphone', 'u.status')
|
||||
->orderBy('u.lastname')
|
||||
->orderBy('u.firstname');
|
||||
|
||||
if ($search !== '') {
|
||||
$needle = '%'.str_replace(['%', '_'], ['\\%', '\\_'], $search).'%';
|
||||
$query->where(function ($inner) use ($needle) {
|
||||
$inner->whereRaw("CONCAT_WS(' ', u.firstname, u.lastname) LIKE ?", [$needle])
|
||||
->orWhere('u.email', 'like', $needle)
|
||||
->orWhere('u.cellphone', 'like', $needle)
|
||||
->orWhereExists(function ($exists) use ($needle) {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as sfg')
|
||||
->join('family_students as sfs', 'sfs.family_id', '=', 'sfg.family_id')
|
||||
->join('students as ss', 'ss.id', '=', 'sfs.student_id')
|
||||
->whereColumn('sfg.user_id', 'u.id')
|
||||
->where(function ($student) use ($needle) {
|
||||
$student->whereRaw("CONCAT_WS(' ', ss.firstname, ss.lastname) LIKE ?", [$needle]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return $query->paginate(max(1, min($perPage, 100)));
|
||||
}
|
||||
|
||||
public function search(string $schoolYear, string $search, int $limit = 10): array
|
||||
{
|
||||
if (trim($search) === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->index($schoolYear, $search, $limit)
|
||||
->getCollection()
|
||||
->map(fn ($row) => $this->parentSummary((array) $row, $schoolYear))
|
||||
->all();
|
||||
}
|
||||
|
||||
public function show(int $parentId, string $schoolYear): ?array
|
||||
{
|
||||
$parent = DB::table('users')
|
||||
->select('id', 'firstname', 'lastname', 'email', 'cellphone', 'address_street', 'city', 'state', 'zip', 'status')
|
||||
->where('id', $parentId)
|
||||
->first();
|
||||
|
||||
if (! $parent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$guardians = [
|
||||
[
|
||||
'user_id' => $parentId,
|
||||
'firstname' => $parent->firstname,
|
||||
'lastname' => $parent->lastname,
|
||||
],
|
||||
];
|
||||
$finance = $this->finance->loadFinancialsForParents([$parentId], $schoolYear);
|
||||
|
||||
return [
|
||||
'parent' => (array) $parent,
|
||||
'families' => $this->familiesForParent($parentId, $schoolYear),
|
||||
'students' => $this->studentsForParent($parentId, $schoolYear),
|
||||
'emergency_contacts' => $this->emergencyContactsForParents($guardians, $schoolYear),
|
||||
'invoices' => $finance['invoices'],
|
||||
'payments' => $finance['payments'],
|
||||
'finance_summary' => $finance['summary'],
|
||||
];
|
||||
}
|
||||
|
||||
public function updateParent(int $parentId, array $payload): ?array
|
||||
{
|
||||
$allowed = array_intersect_key($payload, array_flip([
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'cellphone',
|
||||
'address_street',
|
||||
'city',
|
||||
'state',
|
||||
'zip',
|
||||
'status',
|
||||
]));
|
||||
|
||||
if ($allowed !== []) {
|
||||
$allowed['updated_at'] = now();
|
||||
DB::table('users')->where('id', $parentId)->update($allowed);
|
||||
}
|
||||
|
||||
$parent = DB::table('users')->where('id', $parentId)->first();
|
||||
|
||||
return $parent ? (array) $parent : null;
|
||||
}
|
||||
|
||||
public function parentSummary(array $row, string $schoolYear): array
|
||||
{
|
||||
$balance = (float) ($row['balance'] ?? 0);
|
||||
$primaryFamily = DB::table('family_guardians as fg')
|
||||
->join('families as f', 'f.id', '=', 'fg.family_id')
|
||||
->where('fg.user_id', (int) ($row['id'] ?? 0))
|
||||
->orderByDesc('fg.is_primary')
|
||||
->orderBy('f.household_name')
|
||||
->select('f.id', 'f.household_name')
|
||||
->first();
|
||||
|
||||
return [
|
||||
'id' => (int) ($row['id'] ?? 0),
|
||||
'firstname' => $row['firstname'] ?? null,
|
||||
'lastname' => $row['lastname'] ?? null,
|
||||
'email' => $row['email'] ?? null,
|
||||
'cellphone' => $row['cellphone'] ?? null,
|
||||
'is_active' => strtolower((string) ($row['status'] ?? '')) === 'active',
|
||||
'families_count' => (int) ($row['families_count'] ?? 0),
|
||||
'students_count' => (int) ($row['selected_year_students_count'] ?? 0),
|
||||
'selected_year_students_count' => (int) ($row['selected_year_students_count'] ?? 0),
|
||||
'balance' => $balance,
|
||||
'positive_unpaid_balance' => max(0, $balance),
|
||||
'credit_balance' => $balance < 0 ? abs($balance) : 0.0,
|
||||
'primary_family' => $primaryFamily ? (array) $primaryFamily : null,
|
||||
'school_year' => $schoolYear,
|
||||
];
|
||||
}
|
||||
|
||||
private function relevantParentConstraint(string $schoolYear): callable
|
||||
{
|
||||
return function ($query) use ($schoolYear) {
|
||||
$query->whereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as rfg')
|
||||
->join('family_students as rfs', 'rfs.family_id', '=', 'rfg.family_id')
|
||||
->join('students as rs', 'rs.id', '=', 'rfs.student_id')
|
||||
->whereColumn('rfg.user_id', 'u.id')
|
||||
->where('rs.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('students as direct_students')
|
||||
->whereColumn('direct_students.parent_id', 'u.id')
|
||||
->where('direct_students.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('invoices as ri')
|
||||
->whereColumn('ri.parent_id', 'u.id')
|
||||
->where('ri.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('parent_accounts as pa')
|
||||
->whereColumn('pa.parent_id', 'u.id')
|
||||
->where('pa.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('emergency_contacts as ec')
|
||||
->whereColumn('ec.parent_id', 'u.id')
|
||||
->where('ec.school_year', $schoolYear);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private function familiesForParent(int $parentId, string $schoolYear): array
|
||||
{
|
||||
return DB::table('family_guardians as fg')
|
||||
->join('families as f', 'f.id', '=', 'fg.family_id')
|
||||
->where('fg.user_id', $parentId)
|
||||
->whereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_students as fs')
|
||||
->join('students as s', 's.id', '=', 'fs.student_id')
|
||||
->whereColumn('fs.family_id', 'f.id')
|
||||
->where('s.school_year', $schoolYear);
|
||||
})
|
||||
->orderBy('f.household_name')
|
||||
->select('f.*', 'fg.relation', 'fg.is_primary', 'fg.receive_emails', 'fg.receive_sms')
|
||||
->get()
|
||||
->map(fn ($row) => (array) $row)
|
||||
->all();
|
||||
}
|
||||
|
||||
private function studentsForParent(int $parentId, string $schoolYear): array
|
||||
{
|
||||
$rows = DB::table('students as s')
|
||||
->select('s.id', 's.firstname', 's.lastname', 's.parent_id')
|
||||
->where('s.school_year', $schoolYear)
|
||||
->where(function ($query) use ($parentId) {
|
||||
$query->where('s.parent_id', $parentId)
|
||||
->orWhereExists(function ($exists) use ($parentId) {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as fg')
|
||||
->join('family_students as fs', 'fs.family_id', '=', 'fg.family_id')
|
||||
->whereColumn('fs.student_id', 's.id')
|
||||
->where('fg.user_id', $parentId);
|
||||
});
|
||||
})
|
||||
->orderBy('s.lastname')
|
||||
->orderBy('s.firstname')
|
||||
->get()
|
||||
->map(fn ($row) => (array) $row)
|
||||
->all();
|
||||
|
||||
foreach ($rows as &$row) {
|
||||
$studentId = (int) ($row['id'] ?? 0);
|
||||
$classSectionName = $studentId > 0
|
||||
? (string) (StudentClass::getClassSectionsByStudentId($studentId, $schoolYear) ?? '')
|
||||
: '';
|
||||
$row['class_section_name'] = $classSectionName;
|
||||
$row['grade'] = $classSectionName;
|
||||
}
|
||||
unset($row);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function emergencyContactsForParents(array $guardians, string $schoolYear): array
|
||||
{
|
||||
$parentIds = array_values(array_filter(array_map(
|
||||
static fn ($g) => (int) ($g['user_id'] ?? 0),
|
||||
$guardians
|
||||
)));
|
||||
|
||||
if ($parentIds === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return DB::table('emergency_contacts')
|
||||
->select('id', 'parent_id', 'emergency_contact_name', 'relation', 'cellphone', 'email', 'school_year', 'semester', 'created_at', 'updated_at')
|
||||
->whereIn('parent_id', $parentIds)
|
||||
->where('school_year', $schoolYear)
|
||||
->orderByDesc('updated_at')
|
||||
->get()
|
||||
->map(fn ($row) => (array) $row)
|
||||
->all();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user