Files
alrahma_sunday_school_api/app/Services/Whatsapp/WhatsappContactService.php
T
2026-04-29 17:39:33 -04:00

267 lines
10 KiB
PHP

<?php
namespace App\Services\Whatsapp;
use App\Models\WhatsappGroupMembership;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class WhatsappContactService
{
public function __construct(private WhatsappContextService $context)
{
}
public function listParentContacts(?string $schoolYear, ?string $semester): array
{
$schoolYear = trim((string) $schoolYear);
$semester = trim((string) $semester);
$builder = DB::table('parents as sp');
$builder->select("
sp.id AS parents_row_id,
sp.firstparent_id AS firstparent_id,
sp.secondparent_firstname AS sp_firstname,
sp.secondparent_lastname AS sp_lastname,
sp.secondparent_email AS sp_email,
sp.secondparent_phone AS sp_phone,
sp.school_year AS sp_school_year,
sp.semester AS sp_semester,
u.id AS u_id,
u.firstname AS u_firstname,
u.lastname AS u_lastname,
u.email AS u_email,
u.cellphone AS u_phone,
u.school_year AS u_school_year,
u.semester AS u_semester
");
$builder->leftJoin('users as u', 'u.id', '=', 'sp.firstparent_id');
if ($schoolYear !== '') {
$builder->where('sp.school_year', $schoolYear);
}
if ($semester !== '') {
$builder->where('sp.semester', $semester);
}
$rows = $builder->get()->all();
$contacts = [];
foreach ($rows as $row) {
$r = (array) $row;
if (!empty($r['u_id'])) {
$contacts[] = [
'firstname' => (string) ($r['u_firstname'] ?? ''),
'lastname' => (string) ($r['u_lastname'] ?? ''),
'email' => (string) ($r['u_email'] ?? ''),
'phone' => (string) ($r['u_phone'] ?? ''),
'type' => 'Primary Parent',
];
}
$hasSecond = !empty($r['sp_firstname']) || !empty($r['sp_lastname']) || !empty($r['sp_email']) || !empty($r['sp_phone']);
if ($hasSecond) {
$contacts[] = [
'firstname' => (string) ($r['sp_firstname'] ?? ''),
'lastname' => (string) ($r['sp_lastname'] ?? ''),
'email' => (string) ($r['sp_email'] ?? ''),
'phone' => (string) ($r['sp_phone'] ?? ''),
'type' => 'Second Parent',
];
}
}
$contacts = array_values(array_filter($contacts, function ($c) {
$name = trim(($c['firstname'] ?? '') . ($c['lastname'] ?? ''));
$contact = trim(($c['phone'] ?? '') . ($c['email'] ?? ''));
return $name !== '' || $contact !== '';
}));
usort($contacts, function ($a, $b) {
$la = strtolower($a['lastname'] ?? '');
$lb = strtolower($b['lastname'] ?? '');
if ($la !== $lb) {
return $la <=> $lb;
}
$fa = strtolower($a['firstname'] ?? '');
$fb = strtolower($b['firstname'] ?? '');
if ($fa !== $fb) {
return $fa <=> $fb;
}
$ta = ($a['type'] ?? '') === 'Primary Parent' ? 0 : 1;
$tb = ($b['type'] ?? '') === 'Primary Parent' ? 0 : 1;
return $ta <=> $tb;
});
return $contacts;
}
public function listParentContactsByClass(?string $schoolYear, ?string $semester): array
{
$schoolYear = trim((string) $schoolYear);
$semester = trim((string) $semester);
$sections = DB::table('student_class as sc')
->select('sc.class_section_id', DB::raw('MAX(sc.school_year) AS school_year'))
->when($schoolYear !== '', fn ($q) => $q->where('sc.school_year', $schoolYear))
->groupBy('sc.class_section_id')
->orderBy('sc.class_section_id', 'ASC')
->get()
->all();
$sectionIds = array_values(array_filter(array_unique(array_map(
fn ($r) => (int) ($r->class_section_id ?? 0),
$sections
))));
$namesById = [];
if (!empty($sectionIds)) {
$nameRows = DB::table('classSection')
->select('class_section_id', 'class_section_name')
->whereIn('class_section_id', $sectionIds)
->get()
->all();
foreach ($nameRows as $row) {
$namesById[(int) $row->class_section_id] = (string) ($row->class_section_name ?? '');
}
}
$classSections = [];
foreach ($sections as $s) {
$sid = (int) ($s->class_section_id ?? 0);
if (!$sid) {
continue;
}
$classSections[$sid] = [
'class_section_id' => $sid,
'class_section_name' => $namesById[$sid] ?? ('Section ' . $sid),
'semester' => $semester,
'school_year' => (string) ($s->school_year ?? ''),
'description' => '',
'main_teachers' => [],
'teacher_assistants' => [],
'parents' => [],
];
}
$rows = DB::table('student_class as sc')
->select([
'sc.class_section_id',
'u.id as primary_id',
'u.firstname as primary_firstname',
'u.lastname as primary_lastname',
'u.email as primary_email',
'u.cellphone as primary_phone',
'sp.id as second_id',
'sp.secondparent_firstname as second_firstname',
'sp.secondparent_lastname as second_lastname',
'sp.secondparent_email as second_email',
'sp.secondparent_phone as second_phone',
])
->join('students as s', 's.id', '=', 'sc.student_id')
->join('users as u', 'u.id', '=', 's.parent_id')
->leftJoin('parents as sp', function ($join) {
$join->on('sp.firstparent_id', '=', 'u.id')
->on('sp.school_year', '=', 'sc.school_year');
})
->when($schoolYear !== '', fn ($q) => $q->where('sc.school_year', $schoolYear))
->orderBy('sc.class_section_id', 'ASC')
->orderBy('u.lastname', 'ASC')
->orderBy('u.firstname', 'ASC')
->get()
->all();
$seen = [];
foreach ($rows as $row) {
$r = (array) $row;
$sid = (int) ($r['class_section_id'] ?? 0);
$pid = (int) ($r['primary_id'] ?? 0);
if (!$sid || !$pid || !isset($classSections[$sid])) {
continue;
}
$key = $sid . ':' . $pid;
if (isset($seen[$key])) {
continue;
}
$seen[$key] = true;
$classSections[$sid]['parents'][] = [
'class_section_id' => $sid,
'primary_id' => $pid,
'primary_name' => trim(($r['primary_lastname'] ?? '') . ', ' . ($r['primary_firstname'] ?? '')),
'primary_phone' => (string) ($r['primary_phone'] ?? ''),
'primary_email' => (string) ($r['primary_email'] ?? ''),
'second_id' => (int) ($r['second_id'] ?? 0),
'second_name' => trim(($r['second_lastname'] ?? '') . ', ' . ($r['second_firstname'] ?? '')),
'second_phone' => (string) ($r['second_phone'] ?? ''),
'second_email' => (string) ($r['second_email'] ?? ''),
'primary_member' => null,
'second_member' => null,
];
}
try {
$sectionIds = array_keys($classSections);
$membershipMap = WhatsappGroupMembership::getBySectionsAndTerm($sectionIds, $schoolYear, $semester);
foreach ($classSections as $sid => &$section) {
foreach ($section['parents'] as &$parent) {
$key = sprintf('%d:primary:%d', (int) $parent['class_section_id'], (int) $parent['primary_id']);
if (isset($membershipMap[$key])) {
$parent['primary_member'] = (int) ($membershipMap[$key]['is_member'] ?? 0);
}
$secondId = (int) ($parent['second_id'] ?? 0);
if ($secondId > 0) {
$key2 = sprintf('%d:second:%d', (int) $parent['class_section_id'], $secondId);
if (isset($membershipMap[$key2])) {
$parent['second_member'] = (int) ($membershipMap[$key2]['is_member'] ?? 0);
}
}
}
unset($parent);
}
unset($section);
} catch (\Throwable $e) {
Log::warning('WhatsApp membership lookup failed: ' . $e->getMessage());
}
try {
$teachers = DB::table('teacher_class as tc')
->select('tc.class_section_id', 'tc.position', 'u.firstname', 'u.lastname')
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
->when($schoolYear !== '', fn ($q) => $q->where('tc.school_year', $schoolYear))
->get()
->all();
foreach ($teachers as $row) {
$r = (array) $row;
$sid = (int) ($r['class_section_id'] ?? 0);
if (!isset($classSections[$sid])) {
continue;
}
$name = trim(($r['lastname'] ?? '') . ', ' . ($r['firstname'] ?? ''));
$pos = strtolower((string) ($r['position'] ?? 'main'));
if ($pos === 'ta' || $pos === 'assistant') {
$classSections[$sid]['teacher_assistants'][] = $name;
} else {
$classSections[$sid]['main_teachers'][] = $name;
}
}
} catch (\Throwable $e) {
Log::warning('WhatsApp teacher list lookup failed: ' . $e->getMessage());
}
foreach ($classSections as &$section) {
$section['main_teachers'] = array_values(array_filter($section['main_teachers'] ?? []));
$section['teacher_assistants'] = array_values(array_filter($section['teacher_assistants'] ?? []));
$section['parents'] = array_values($section['parents'] ?? []);
}
unset($section);
return array_values($classSections);
}
}