add whatsup logic

This commit is contained in:
root
2026-03-10 16:31:35 -04:00
parent 20ee70d153
commit 3bf4c687da
33 changed files with 2800 additions and 1329 deletions
@@ -0,0 +1,57 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Services\Whatsapp\WhatsappContactService;
use App\Services\Whatsapp\WhatsappContextService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class WhatsappContactServiceTest extends TestCase
{
use RefreshDatabase;
public function test_list_parent_contacts_returns_primary_and_second(): void
{
DB::table('users')->insert([
'id' => 10,
'school_id' => 1,
'firstname' => 'Parent',
'lastname' => 'One',
'cellphone' => '5555555555',
'email' => 'parent1@example.com',
'address_street' => '123 Main',
'city' => 'City',
'state' => 'ST',
'zip' => '12345',
'accept_school_policy' => 1,
'is_verified' => 1,
'status' => 'Active',
'is_suspended' => 0,
'failed_attempts' => 0,
'password' => bcrypt('secret'),
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
DB::table('parents')->insert([
'secondparent_firstname' => 'Parent',
'secondparent_lastname' => 'Two',
'secondparent_email' => 'parent2@example.com',
'secondparent_phone' => '5555555555',
'firstparent_id' => 10,
'school_year' => '2025-2026',
'semester' => 'Fall',
'created_at' => now(),
'updated_at' => now(),
]);
$service = new WhatsappContactService(new WhatsappContextService());
$contacts = $service->listParentContacts('2025-2026', 'Fall');
$this->assertCount(2, $contacts);
$this->assertSame('Primary Parent', $contacts[0]['type']);
$this->assertSame('Second Parent', $contacts[1]['type']);
}
}
@@ -0,0 +1,41 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Services\Whatsapp\WhatsappContextService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class WhatsappContextServiceTest extends TestCase
{
use RefreshDatabase;
public function test_school_year_aliases_generate_expected_values(): void
{
$service = new WhatsappContextService();
[$aliases, $canonical, $startYear] = $service->schoolYearAliases('2025/2026');
$this->assertContains('2025-2026', $aliases);
$this->assertSame('2025-2026', $canonical);
$this->assertSame(2025, $startYear);
}
public function test_has_roster_for_year(): void
{
DB::table('student_class')->insert([
'student_id' => 1,
'class_section_id' => 1,
'school_year' => '2025-2026',
'semester' => 'Fall',
'is_event_only' => 0,
'created_at' => now(),
'updated_at' => now(),
]);
$service = new WhatsappContextService();
$this->assertTrue($service->hasRosterForYear('2025-2026'));
$this->assertFalse($service->hasRosterForYear('2030-2031'));
}
}
@@ -0,0 +1,110 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Services\Whatsapp\WhatsappInviteBundleService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class WhatsappInviteBundleServiceTest extends TestCase
{
use RefreshDatabase;
public function test_bundle_for_parent_returns_links_and_emails(): void
{
DB::table('users')->insert([
'id' => 10,
'school_id' => 1,
'firstname' => 'Parent',
'lastname' => 'One',
'cellphone' => '5555555555',
'email' => 'parent1@example.com',
'address_street' => '123 Main',
'city' => 'City',
'state' => 'ST',
'zip' => '12345',
'accept_school_policy' => 1,
'is_verified' => 1,
'status' => 'Active',
'is_suspended' => 0,
'failed_attempts' => 0,
'password' => bcrypt('secret'),
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
DB::table('parents')->insert([
'secondparent_firstname' => 'Parent',
'secondparent_lastname' => 'Two',
'secondparent_email' => 'parent2@example.com',
'secondparent_phone' => '5555555555',
'firstparent_id' => 10,
'school_year' => '2025-2026',
'semester' => 'Fall',
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('students')->insert([
'id' => 100,
'school_id' => 1,
'firstname' => 'Student',
'lastname' => 'One',
'parent_id' => 10,
'semester' => 'Fall',
'school_year' => '2025-2026',
'is_active' => 1,
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('student_class')->insert([
'student_id' => 100,
'class_section_id' => 200,
'school_year' => '2025-2026',
'semester' => 'Fall',
'is_event_only' => 0,
'created_at' => now(),
'updated_at' => now(),
]);
$linkBySection = [
200 => [
'class_section_id' => 200,
'class_section_name' => 'Grade 1',
'invite_link' => 'https://chat.whatsapp.com/abc',
],
];
$service = new WhatsappInviteBundleService();
$bundle = $service->bundleForParent(10, $linkBySection, '2025-2026', 'Fall');
$this->assertNotNull($bundle);
$this->assertNotEmpty($bundle['emails']);
$this->assertNotEmpty($bundle['links']);
}
public function test_consolidate_bundles_merges_by_parent(): void
{
$service = new WhatsappInviteBundleService();
$merged = $service->consolidateBundles([
[
'parent' => ['id' => 10],
'emails' => ['a@example.com'],
'sections' => [['class_section_id' => 1]],
'links' => ['https://chat.whatsapp.com/a'],
],
[
'parent' => ['id' => 10],
'emails' => ['b@example.com'],
'sections' => [['class_section_id' => 2]],
'links' => ['https://chat.whatsapp.com/b'],
],
]);
$this->assertCount(1, $merged);
$this->assertCount(2, $merged[0]['emails']);
}
}
@@ -0,0 +1,39 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Events\WhatsappInvitesSend;
use App\Services\Whatsapp\WhatsappInviteNotificationService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class WhatsappInviteNotificationServiceTest extends TestCase
{
use RefreshDatabase;
public function test_dispatch_returns_error_when_no_listeners(): void
{
$service = new WhatsappInviteNotificationService();
$result = $service->dispatch([], '2025-2026', 'Fall');
$this->assertFalse($result['ok']);
}
public function test_dispatch_triggers_event_when_listener_registered(): void
{
Event::listen(WhatsappInvitesSend::class, static function () {
});
$service = new WhatsappInviteNotificationService();
$result = $service->dispatch([[
'parent' => ['id' => 10],
'emails' => ['parent1@example.com'],
'sections' => [],
'links' => ['https://chat.whatsapp.com/abc'],
]], '2025-2026', 'Fall');
$this->assertTrue($result['ok']);
$this->assertSame(1, $result['triggered']);
}
}
@@ -0,0 +1,111 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Events\WhatsappInvitesSend;
use App\Services\Whatsapp\WhatsappContextService;
use App\Services\Whatsapp\WhatsappInviteBundleService;
use App\Services\Whatsapp\WhatsappInviteNotificationService;
use App\Services\Whatsapp\WhatsappInviteService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class WhatsappInviteServiceTest extends TestCase
{
use RefreshDatabase;
public function test_send_returns_success_for_parent_mode(): void
{
$this->seedInviteData();
Event::listen(WhatsappInvitesSend::class, static function () {
});
$service = new WhatsappInviteService(
new WhatsappContextService(),
new WhatsappInviteBundleService(),
new WhatsappInviteNotificationService()
);
$result = $service->send([
'mode' => 'parents',
'parent_ids' => [10],
'school_year' => '2025-2026',
'semester' => 'Fall',
]);
$this->assertTrue($result['ok']);
$this->assertGreaterThanOrEqual(1, $result['triggered']);
}
private function seedInviteData(): void
{
DB::table('users')->insert([
'id' => 10,
'school_id' => 1,
'firstname' => 'Parent',
'lastname' => 'One',
'cellphone' => '5555555555',
'email' => 'parent1@example.com',
'address_street' => '123 Main',
'city' => 'City',
'state' => 'ST',
'zip' => '12345',
'accept_school_policy' => 1,
'is_verified' => 1,
'status' => 'Active',
'is_suspended' => 0,
'failed_attempts' => 0,
'password' => bcrypt('secret'),
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
DB::table('parents')->insert([
'secondparent_firstname' => 'Parent',
'secondparent_lastname' => 'Two',
'secondparent_email' => 'parent2@example.com',
'secondparent_phone' => '5555555555',
'firstparent_id' => 10,
'school_year' => '2025-2026',
'semester' => 'Fall',
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('students')->insert([
'id' => 100,
'school_id' => 1,
'firstname' => 'Student',
'lastname' => 'One',
'parent_id' => 10,
'semester' => 'Fall',
'school_year' => '2025-2026',
'is_active' => 1,
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('student_class')->insert([
'student_id' => 100,
'class_section_id' => 200,
'school_year' => '2025-2026',
'semester' => 'Fall',
'is_event_only' => 0,
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('whatsapp_group_links')->insert([
'class_section_id' => 200,
'class_section_name' => 'Grade 1',
'school_year' => '2025-2026',
'semester' => 'Fall',
'invite_link' => 'https://chat.whatsapp.com/abc',
'active' => 1,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
@@ -0,0 +1,66 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Services\Whatsapp\WhatsappContextService;
use App\Services\Whatsapp\WhatsappLinkService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class WhatsappLinkServiceTest extends TestCase
{
use RefreshDatabase;
public function test_upsert_creates_link(): void
{
$service = new WhatsappLinkService(new WhatsappContextService());
$link = $service->upsert([
'class_section_id' => 300,
'class_section_name' => 'Grade 6',
'school_year' => '2025-2026',
'semester' => 'Fall',
'invite_link' => 'https://chat.whatsapp.com/grade6',
'active' => true,
]);
$this->assertNotEmpty($link->id);
$this->assertDatabaseHas('whatsapp_group_links', [
'class_section_id' => 300,
'invite_link' => 'https://chat.whatsapp.com/grade6',
]);
}
public function test_paginate_filters_by_active(): void
{
DB::table('whatsapp_group_links')->insert([
[
'class_section_id' => 301,
'class_section_name' => 'Grade 7',
'school_year' => '2025-2026',
'semester' => 'Fall',
'invite_link' => 'https://chat.whatsapp.com/a',
'active' => 1,
'created_at' => now(),
'updated_at' => now(),
],
[
'class_section_id' => 302,
'class_section_name' => 'Grade 8',
'school_year' => '2025-2026',
'semester' => 'Fall',
'invite_link' => 'https://chat.whatsapp.com/b',
'active' => 0,
'created_at' => now(),
'updated_at' => now(),
],
]);
$service = new WhatsappLinkService(new WhatsappContextService());
$page = $service->paginate(['active' => true]);
$this->assertCount(1, $page->items());
$this->assertSame(301, $page->items()[0]->class_section_id);
}
}
@@ -0,0 +1,49 @@
<?php
namespace Tests\Unit\Services\Whatsapp;
use App\Services\Whatsapp\WhatsappMembershipService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class WhatsappMembershipServiceTest extends TestCase
{
use RefreshDatabase;
public function test_update_membership_saves_primary(): void
{
$service = new WhatsappMembershipService();
$result = $service->updateMembership([
'class_section_id' => 200,
'primary_id' => 10,
'primary_member' => true,
'school_year' => '2025-2026',
'semester' => 'Fall',
], 1);
$this->assertTrue($result['ok']);
$this->assertDatabaseHas('whatsapp_group_memberships', [
'class_section_id' => 200,
'subject_type' => 'primary',
'subject_id' => 10,
'is_member' => 1,
]);
}
public function test_update_membership_returns_error_when_table_missing(): void
{
Schema::shouldReceive('hasTable')->with('whatsapp_group_memberships')->andReturn(false);
$service = new WhatsappMembershipService();
$result = $service->updateMembership([
'class_section_id' => 200,
'primary_id' => 10,
'primary_member' => true,
]);
$this->assertFalse($result['ok']);
$this->assertSame('Membership table missing. Please run migrations.', $result['message']);
}
}