Files
alrahma_sunday_school/app/Services/FamilyDataSyncService.php
T
root 1787144f27
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 48s
Tests / PHPUnit (push) Failing after 1m27s
fix family card issue
2026-09-12 03:16:10 -04:00

121 lines
4.1 KiB
PHP

<?php
namespace App\Services;
use CodeIgniter\Database\BaseConnection;
/**
* Keeps the normalized family record aligned with its primary parent and
* every current student owned by that parent.
*/
final class FamilyDataSyncService
{
public function __construct(private readonly BaseConnection $db)
{
}
public function syncForParent(int $parentId): ?int
{
if ($parentId <= 0) {
return null;
}
foreach (['users', 'students', 'families', 'family_guardians', 'family_students'] as $table) {
if (! $this->db->tableExists($table)) {
return null;
}
}
$parent = $this->db->table('users')
->select('id, firstname, lastname, cellphone, address_street, apt, city, state, zip')
->where('id', $parentId)
->get()
->getRowArray();
if (! $parent) {
return null;
}
$familyCode = 'FAM-' . $parentId;
$family = $this->db->table('families')
->select('id')
->where('family_code', $familyCode)
->get()
->getRowArray();
if (! $family) {
$family = $this->db->table('family_guardians fg')
->select('fg.family_id AS id')
->join('families f', 'f.id = fg.family_id', 'inner')
->where('fg.user_id', $parentId)
->orderBy('fg.is_primary', 'DESC')
->orderBy('fg.id', 'ASC')
->get(1)
->getRowArray();
}
$familyData = $this->familyData($parent);
if (! $family) {
$this->db->table('families')->insert(['family_code' => $familyCode] + $familyData);
$familyId = (int) $this->db->insertID();
} else {
$familyId = (int) ($family['id'] ?? 0);
if ($familyId > 0) {
$this->db->table('families')->where('id', $familyId)->update($familyData);
}
}
if ($familyId <= 0) {
throw new \RuntimeException('Family data could not be synchronized for parent ID ' . $parentId . '.');
}
$this->db->query(
'INSERT IGNORE INTO family_guardians (family_id, user_id, relation, is_primary, receive_emails, receive_sms) VALUES (?, ?, ?, 1, 1, 0)',
[$familyId, $parentId, 'primary']
);
$students = $this->db->table('students')
->select('id')
->where('parent_id', $parentId)
->get()
->getResultArray();
foreach ($students as $student) {
$studentId = (int) ($student['id'] ?? 0);
if ($studentId > 0) {
$this->db->query(
'INSERT IGNORE INTO family_students (family_id, student_id, is_primary_home) VALUES (?, ?, 1)',
[$familyId, $studentId]
);
}
}
// Normally handled by the foreign key cascade; this also heals older
// databases where that constraint was absent.
$this->db->query(
'DELETE fs FROM family_students fs LEFT JOIN students s ON s.id = fs.student_id WHERE fs.family_id = ? AND s.id IS NULL',
[$familyId]
);
return $familyId;
}
private function familyData(array $parent): array
{
$parentName = trim((string) ($parent['firstname'] ?? '') . ' ' . (string) ($parent['lastname'] ?? ''));
$data = [
'household_name' => $parentName !== '' ? 'Family of ' . $parentName : 'Family of User ' . (int) $parent['id'],
'address_line1' => trim((string) ($parent['address_street'] ?? '')),
'address_line2' => trim((string) ($parent['apt'] ?? '')),
'city' => trim((string) ($parent['city'] ?? '')),
'state' => trim((string) ($parent['state'] ?? '')),
'postal_code' => trim((string) ($parent['zip'] ?? '')),
'primary_phone' => trim((string) ($parent['cellphone'] ?? '')),
'is_active' => 1,
];
if ($this->db->fieldExists('updated_at', 'families')) {
$data['updated_at'] = utc_now();
}
return $data;
}
}