define('ROOT_PATH', dirname(__DIR__)); require_once ROOT_PATH . '/app/core/Autoloader.php'; \App\Core\Autoloader::register(); $bootstrap = new \App\Core\Bootstrap(); $bootstrap->init(); use App\Core\Database; use App\Modules\Guest\GuestModel; use App\Modules\Invitation\InvitationModel; use App\Modules\Operation\OperationModel; function run_assert(string $label, bool $assertion) { if ($assertion) { echo "āœ… PASS: {$label}\n"; } else { echo "āŒ FAIL: {$label}\n"; exit(1); } } try { $db = Database::getConnection(); $workspaceId = 83; // Standard workspace ID used in tests $guestModel = new GuestModel(); $invitationModel = new InvitationModel(); $opModel = new OperationModel(); echo "--- RC-014 Backend Logic Verification ---\n"; // 1. Clean up and setup test data $db->prepare('DELETE FROM wishes WHERE workspace_id = :workspace_id AND sender_name LIKE "Test Wish %"')->execute(['workspace_id' => $workspaceId]); $db->prepare('DELETE FROM checkins WHERE workspace_id = :workspace_id AND notes = "Test RC-014 Check-In"')->execute(['workspace_id' => $workspaceId]); $db->prepare('DELETE FROM guests WHERE workspace_id = :workspace_id AND full_name LIKE "Test Guest %"')->execute(['workspace_id' => $workspaceId]); // Create test guests $guestId1 = $guestModel->insertGuest($workspaceId, [ 'guest_code' => 'acttestguest1111', 'full_name' => 'Test Guest Alpha', 'phone_number' => '6281234567891', 'invited_pax' => 2, 'guest_group' => 'vip' ]); $guestId2 = $guestModel->insertGuest($workspaceId, [ 'guest_code' => 'acttestguest2222', 'full_name' => 'Test Guest Beta', 'phone_number' => '6281234567892', 'invited_pax' => 3, 'guest_group' => 'family' ]); // 2. RSVP Center Stats $totalCount = $guestModel->getGuestsCount($workspaceId); $confirmedCount = $guestModel->getGuestsCount($workspaceId, ['rsvp' => 'attending']); $declinedCount = $guestModel->getGuestsCount($workspaceId, ['rsvp' => 'declined']); $pendingCount = $guestModel->getGuestsCount($workspaceId, ['rsvp' => 'pending']); run_assert("Expected total guests count is >= 2", $totalCount >= 2); run_assert("Confirmed guests count is matching database", is_int($confirmedCount)); run_assert("Declined guests count is matching database", is_int($declinedCount)); run_assert("Pending guests count is matching database", is_int($pendingCount)); // Update RSVP response $stmtUpd = $db->prepare('UPDATE guests SET rsvp_status = "attending", rsvp_submitted_at = CURRENT_TIMESTAMP WHERE id = :id'); $stmtUpd->execute(['id' => $guestId1]); $confirmedCountAfter = $guestModel->getGuestsCount($workspaceId, ['rsvp' => 'attending']); run_assert("Confirmed guests count increased by 1", $confirmedCountAfter === ($confirmedCount + 1)); // 3. Guest Wishes Center // Insert test wishes $db->prepare('INSERT INTO wishes (workspace_id, guest_id, sender_name, message, is_visible, submitted_at) VALUES (:ws, :g, "Test Wish Alpha", "Wishing you a happy life!", 1, "2026-07-13 10:00:00")') ->execute(['ws' => $workspaceId, 'g' => $guestId1]); $db->prepare('INSERT INTO wishes (workspace_id, guest_id, sender_name, message, is_visible, submitted_at) VALUES (:ws, :g, "Test Wish Beta", "Best congratulations!", 1, "2026-07-13 11:00:00")') ->execute(['ws' => $workspaceId, 'g' => $guestId2]); $wishesFiltered = $invitationModel->getWishesFiltered($workspaceId, ['search' => 'Wish Alpha']); run_assert("Should find wish by search filter", count($wishesFiltered) === 1); run_assert("Search matches correct wish", $wishesFiltered[0]['sender_name'] === 'Test Wish Alpha'); $wishesNewest = $invitationModel->getWishesFiltered($workspaceId, [], 2, 0); run_assert("Should fetch correct limit size", count($wishesNewest) <= 2); run_assert("Sorting newest displays Beta first", $wishesNewest[0]['sender_name'] === 'Test Wish Beta'); $wishesOldest = $invitationModel->getWishesFiltered($workspaceId, ['sort' => 'oldest'], 2, 0); run_assert("Sorting oldest displays Alpha first", $wishesOldest[0]['sender_name'] === 'Test Wish Alpha'); // 4. WhatsApp Queue & Invitation Status Changes // Verify default invitation_status is 'not_sent' $stmtStatus = $db->prepare('SELECT invitation_status FROM guests WHERE id = :id'); $stmtStatus->execute(['id' => $guestId1]); run_assert("Default invitation status is 'not_sent'", $stmtStatus->fetchColumn() === 'not_sent'); // Mark as sent $db->prepare('UPDATE guests SET invitation_status = "sent", updated_at = CURRENT_TIMESTAMP WHERE id = :id')->execute(['id' => $guestId1]); $stmtStatus->execute(['id' => $guestId1]); run_assert("Invitation status successfully updated to 'sent'", $stmtStatus->fetchColumn() === 'sent'); // Reset queue $db->prepare('UPDATE guests SET invitation_status = "not_sent", updated_at = CURRENT_TIMESTAMP WHERE workspace_id = :ws AND is_deleted = 0')->execute(['ws' => $workspaceId]); $stmtStatus->execute(['id' => $guestId1]); run_assert("Reset queue updates status back to 'not_sent'", $stmtStatus->fetchColumn() === 'not_sent'); // 5. Dashboard Recent Activities // Perform a checkin $db->prepare('INSERT INTO checkins (workspace_id, guest_id, wedding_event_id, operator_id, checkin_method, notes, checked_in_at) VALUES (:ws, :g, 1, 1008, "manual", "Test RC-014 Check-In", CURRENT_TIMESTAMP)') ->execute(['ws' => $workspaceId, 'g' => $guestId1]); // Fetch Recent RSVPs (last 5 rsvp updates) $stmtRecentRsvps = $db->prepare(' SELECT full_name, rsvp_status, rsvp_submitted_at FROM guests WHERE workspace_id = :workspace_id AND is_deleted = 0 AND rsvp_status != "pending" ORDER BY rsvp_submitted_at DESC LIMIT 5 '); $stmtRecentRsvps->execute(['workspace_id' => $workspaceId]); $recentRsvps = $stmtRecentRsvps->fetchAll(\PDO::FETCH_ASSOC); run_assert("Recent RSVPs is an array", is_array($recentRsvps)); run_assert("Recent RSVPs contains our newly updated guest", $recentRsvps[0]['full_name'] === 'Test Guest Alpha'); // Fetch Recent Check-Ins (last 5 successful check-ins) $stmtRecentCheckins = $db->prepare(' SELECT g.full_name, c.checked_in_at, e.event_name FROM checkins c INNER JOIN guests g ON c.guest_id = g.id INNER JOIN wedding_events e ON c.wedding_event_id = e.id WHERE c.workspace_id = :workspace_id AND g.is_deleted = 0 ORDER BY c.checked_in_at DESC LIMIT 5 '); $stmtRecentCheckins->execute(['workspace_id' => $workspaceId]); $recentCheckins = $stmtRecentCheckins->fetchAll(\PDO::FETCH_ASSOC); run_assert("Recent Check-Ins is an array", is_array($recentCheckins)); run_assert("Recent Check-Ins contains our new check-in guest", $recentCheckins[0]['full_name'] === 'Test Guest Alpha'); // Cleanup test data $db->prepare('DELETE FROM wishes WHERE workspace_id = :workspace_id AND sender_name LIKE "Test Wish %"')->execute(['workspace_id' => $workspaceId]); $db->prepare('DELETE FROM checkins WHERE workspace_id = :workspace_id AND notes = "Test RC-014 Check-In"')->execute(['workspace_id' => $workspaceId]); $db->prepare('DELETE FROM guests WHERE workspace_id = :workspace_id AND full_name LIKE "Test Guest %"')->execute(['workspace_id' => $workspaceId]); echo "\nšŸŽ‰ ALL BACKEND LOGIC VERIFICATIONS PASSED SUCCESSFULLY!\n"; } catch (\Throwable $e) { echo "āŒ EXCEPTION: " . $e->getMessage() . " at " . $e->getFile() . ":" . $e->getLine() . "\n"; exit(1); }