Files
nabeh/backend/app/Controllers/SuperAdminController.php
2026-05-23 03:23:22 +03:00

189 lines
7.4 KiB
PHP

<?php
namespace App\Controllers;
use App\Core\Request;
use App\Core\Response;
use App\Core\Database;
use App\Models\CompanySubscription;
class SuperAdminController extends BaseController
{
/**
* Helper to verify if the requester is the Super Admin (Company ID 1 and role Admin)
*/
private function verifySuperAdmin(Request $request, Response $response): bool
{
if ((int)$request->company_id !== 1 || $request->role !== 'admin') {
$response->status(403)->json(['error' => 'Forbidden: Super Admin privileges required.']);
return false;
}
return true;
}
/**
* Get platform statistics and companies list
* GET /api/admin/stats
*/
public function getStats(Request $request, Response $response): void
{
if (!$this->verifySuperAdmin($request, $response)) {
return;
}
try {
// Overall stats
$companiesCount = Database::selectOne("SELECT COUNT(*) as count FROM companies")['count'] ?? 0;
$sessionsCount = Database::selectOne("SELECT COUNT(*) as count FROM whatsapp_sessions")['count'] ?? 0;
$connectedSessions = Database::selectOne("SELECT COUNT(*) as count FROM whatsapp_sessions WHERE status = 'connected'")['count'] ?? 0;
// Detailed list of all companies and their current subscriptions
$companies = Database::select("
SELECT
c.id,
c.name,
c.status,
cs.plan_id,
sp.name as plan_name,
cs.status as subscription_status,
SELECT c.id, c.name, c.status as company_status, c.created_at,
cs.plan_id, cs.status as sub_status, cs.starts_at, cs.ends_at, cs.payment_method, cs.receipt_reference,
p.name as plan_name
FROM companies c
LEFT JOIN company_subscriptions cs ON c.id = cs.company_id AND cs.status IN ('active', 'trialing', 'pending_approval')
LEFT JOIN subscription_plans p ON cs.plan_id = p.id
ORDER BY c.created_at DESC
");
$pendingApprovals = [];
$activeCompanies = [];
foreach ($companies as $c) {
if ($c['sub_status'] === 'pending_approval') {
$pendingApprovals[] = $c;
} else {
$activeCompanies[] = $c;
}
}
// 4. Fetch all available plans to allow admin to upgrade them manually
$plans = Database::select("SELECT id, name, price FROM subscription_plans ORDER BY price ASC");
$response->json([
'status' => 'success',
'data' => [
'stats' => [
'total_companies' => (int)$companiesCount,
'total_sessions' => (int)$sessionsCount,
'connected_sessions' => (int)$connectedSessions
],
'companies' => $activeCompanies,
'pending_approvals' => $pendingApprovals,
'plans' => $plans
]
]);
} catch (\Exception $e) {
error_log("[SuperAdminController Error] " . $e->getMessage());
$response->status(500)->json(['error' => 'Failed to fetch platform stats: ' . $e->getMessage()]);
}
}
/**
* Subscribe or upgrade a company to a plan
* POST /api/admin/companies/subscribe
*/
public function subscribeCompany(Request $request, Response $response): void
{
if (!$this->verifySuperAdmin($request, $response)) {
return;
}
$body = $request->getBody();
$targetCompanyId = isset($body['company_id']) ? (int)$body['company_id'] : null;
$planId = isset($body['plan_id']) ? (int)$body['plan_id'] : null;
$durationDays = isset($body['duration_days']) ? (int)$body['duration_days'] : 30;
if (!$targetCompanyId || !$planId) {
$response->status(400)->json(['error' => 'Missing company_id or plan_id']);
return;
}
// Verify company exists
$companyExists = Database::selectOne("SELECT id FROM companies WHERE id = ?", [$targetCompanyId]);
if (!$companyExists) {
$response->status(404)->json(['error' => 'Company not found']);
return;
}
// Verify plan exists
$planExists = Database::selectOne("SELECT id FROM subscription_plans WHERE id = ?", [$planId]);
if (!$planExists) {
$response->status(404)->json(['error' => 'Subscription plan not found']);
return;
}
try {
// Subscribe the company
$subId = CompanySubscription::subscribeCompany($targetCompanyId, $planId, $durationDays, 'manual_admin', 'admin_' . $request->user_id);
// Clean active subscription cache for the company
if (class_exists('App\Core\Cache')) {
\App\Core\Cache::delete("company_subscription:{$targetCompanyId}");
\App\Core\Cache::delete("company_subscription_{$targetCompanyId}");
}
$response->json([
'status' => 'success',
'message' => 'Subscription updated successfully',
'subscription_id' => $subId
]);
} catch (\Exception $e) {
error_log("[SuperAdminController Error] " . $e->getMessage());
$response->status(500)->json(['error' => 'Failed to update subscription: ' . $e->getMessage()]);
}
}
/**
* Approve a pending billing request
* POST /api/admin/companies/approve-billing
*/
public function approveBilling(Request $request, Response $response): void
{
$body = $request->getBody();
$targetCompanyId = isset($body['company_id']) ? (int)$body['company_id'] : null;
if (!$targetCompanyId) {
$response->status(400)->json(['error' => 'Missing company_id']);
return;
}
try {
// Find the pending subscription
$pending = Database::selectOne("SELECT * FROM company_subscriptions WHERE company_id = ? AND status = 'pending_approval' ORDER BY id DESC LIMIT 1", [$targetCompanyId]);
if (!$pending) {
$response->status(404)->json(['error' => 'No pending approval found for this company']);
return;
}
// Deactivate other active/trialing subscriptions
Database::execute("UPDATE company_subscriptions SET status = 'expired' WHERE company_id = ? AND status IN ('active', 'trialing')", [$targetCompanyId]);
// Mark the pending one as active
Database::execute("UPDATE company_subscriptions SET status = 'active' WHERE id = ?", [$pending['id']]);
// Clear active subscription cache for the company
if (class_exists('App\Core\Cache')) {
\App\Core\Cache::delete("company_subscription_{$targetCompanyId}");
}
$response->json([
'status' => 'success',
'message' => 'Billing approved and subscription activated successfully'
]);
} catch (\Exception $e) {
$response->status(500)->json(['error' => 'Failed to approve billing: ' . $e->getMessage()]);
}
}
}