Many fixes
This commit is contained in:
+233
-215
@@ -2,22 +2,31 @@
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\OrganizationModel;
|
||||
use App\Models\OrganizationSubscriptionModel;
|
||||
use App\Models\OrganizationUserModel;
|
||||
use App\Models\UserModel;
|
||||
use App\Services\ModuleSubscriptionService;
|
||||
|
||||
/**
|
||||
* Superadmin - Панель суперадмина
|
||||
*
|
||||
* Управление системой: тарифы, организации, пользователи.
|
||||
* Управление системой: модули, подписки организаций, пользователи.
|
||||
*/
|
||||
class Superadmin extends BaseController
|
||||
{
|
||||
protected $organizationModel;
|
||||
protected $userModel;
|
||||
protected $planModel;
|
||||
protected $subscriptionModel;
|
||||
protected ?OrganizationUserModel $orgUserModel = null;
|
||||
protected ModuleSubscriptionService $subscriptionService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->organizationModel = new \App\Models\OrganizationModel();
|
||||
$this->userModel = new \App\Models\UserModel();
|
||||
$this->planModel = new \App\Models\PlanModel();
|
||||
$this->organizationModel = new OrganizationModel();
|
||||
$this->userModel = new UserModel();
|
||||
$this->subscriptionModel = new OrganizationSubscriptionModel();
|
||||
$this->subscriptionService = service('moduleSubscription');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,20 +34,17 @@ class Superadmin extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// Статистика
|
||||
$stats = [
|
||||
'total_users' => $this->userModel->countAll(),
|
||||
'total_orgs' => $this->organizationModel->countAll(),
|
||||
'active_today' => $this->userModel->where('created_at >=', date('Y-m-d'))->countAllResults(),
|
||||
'total_plans' => $this->planModel->countAll(),
|
||||
'total_modules' => count($this->subscriptionService->getAllModules()),
|
||||
];
|
||||
|
||||
// Последние организации
|
||||
$recentOrgs = $this->organizationModel
|
||||
->orderBy('created_at', 'DESC')
|
||||
->findAll(5);
|
||||
|
||||
// Последние пользователи
|
||||
$recentUsers = $this->userModel
|
||||
->orderBy('created_at', 'DESC')
|
||||
->findAll(5);
|
||||
@@ -47,135 +53,204 @@ class Superadmin extends BaseController
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// УПРАВЛЕНИЕ ТАРИФАМИ
|
||||
// УПРАВЛЕНИЕ МОДУЛЯМИ
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Список тарифов
|
||||
* Список модулей с ценами
|
||||
*/
|
||||
public function plans()
|
||||
public function modules()
|
||||
{
|
||||
$plans = $this->planModel->findAll();
|
||||
// Декодируем features для Twig
|
||||
foreach ($plans as &$plan) {
|
||||
$plan['features'] = json_decode($plan['features'] ?? '[]', true);
|
||||
}
|
||||
$modules = $this->subscriptionService->getAllModules();
|
||||
|
||||
return $this->renderTwig('superadmin/plans/index', compact('plans'));
|
||||
return $this->renderTwig('superadmin/modules/index', compact('modules'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Создание тарифа (форма)
|
||||
* Обновление параметров модуля
|
||||
*/
|
||||
public function createPlan()
|
||||
public function updateModule()
|
||||
{
|
||||
return $this->renderTwig('superadmin/plans/create');
|
||||
}
|
||||
$moduleCode = $this->request->getPost('module_code');
|
||||
$config = $this->subscriptionService->getModuleConfig($moduleCode);
|
||||
|
||||
/**
|
||||
* Сохранение тарифа
|
||||
*/
|
||||
public function storePlan()
|
||||
{
|
||||
// Получаем features из текстового поля (каждая строка - отдельная возможность)
|
||||
$featuresText = $this->request->getPost('features_list');
|
||||
$features = [];
|
||||
if ($featuresText) {
|
||||
$lines = explode("\n", trim($featuresText));
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
$features[] = $line;
|
||||
}
|
||||
}
|
||||
if (!$moduleCode || !$config) {
|
||||
return redirect()->back()->with('error', 'Модуль не найден');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->request->getPost('name'),
|
||||
'description' => $this->request->getPost('description'),
|
||||
'price' => (float) $this->request->getPost('price'),
|
||||
'currency' => $this->request->getPost('currency') ?? 'RUB',
|
||||
'billing_period' => $this->request->getPost('billing_period') ?? 'monthly',
|
||||
'max_users' => (int) $this->request->getPost('max_users'),
|
||||
'max_clients' => (int) $this->request->getPost('max_clients'),
|
||||
'max_storage' => (int) $this->request->getPost('max_storage'),
|
||||
'features' => json_encode($features),
|
||||
'is_active' => $this->request->getPost('is_active') ?? 1,
|
||||
'is_default' => $this->request->getPost('is_default') ?? 0,
|
||||
$this->subscriptionService->saveModuleSettings(
|
||||
$moduleCode,
|
||||
$this->request->getPost('name'),
|
||||
$this->request->getPost('description'),
|
||||
(int) $this->request->getPost('price_monthly'),
|
||||
(int) $this->request->getPost('price_yearly'),
|
||||
(int) $this->request->getPost('trial_days')
|
||||
);
|
||||
|
||||
return redirect()->to('/superadmin/modules')->with('success', 'Модуль успешно обновлён');
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// УПРАВЛЕНИЕ ПОДПИСКАМИ
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Конфигурация таблицы подписок
|
||||
*/
|
||||
protected function getSubscriptionsTableConfig(): array
|
||||
{
|
||||
return [
|
||||
'id' => 'subscriptions-table',
|
||||
'url' => '/superadmin/subscriptions/table',
|
||||
'model' => $this->subscriptionModel,
|
||||
'columns' => [
|
||||
'id' => ['label' => 'ID', 'width' => '60px'],
|
||||
'organization_name' => ['label' => 'Организация'],
|
||||
'module_code' => ['label' => 'Модуль', 'width' => '100px'],
|
||||
'status' => ['label' => 'Статус', 'width' => '100px'],
|
||||
'expires_at' => ['label' => 'Истекает', 'width' => '120px'],
|
||||
'created_at' => ['label' => 'Создана', 'width' => '120px'],
|
||||
],
|
||||
'searchable' => ['id', 'organization_name', 'module_code'],
|
||||
'sortable' => ['id', 'created_at', 'expires_at'],
|
||||
'defaultSort' => 'created_at',
|
||||
'order' => 'desc',
|
||||
'fieldMap' => [
|
||||
'organization_name' => 'organizations.name',
|
||||
'id' => 'organization_subscriptions.id',
|
||||
'module_code' => 'organization_subscriptions.module_code',
|
||||
'status' => 'organization_subscriptions.status',
|
||||
'expires_at' => 'organization_subscriptions.expires_at',
|
||||
'created_at' => 'organization_subscriptions.created_at',
|
||||
],
|
||||
'scope' => function ($builder) {
|
||||
$builder->from('organization_subscriptions')
|
||||
->select('organization_subscriptions.*, organizations.name as organization_name')
|
||||
->join('organizations', 'organizations.id = organization_subscriptions.organization_id');
|
||||
},
|
||||
'actions' => ['label' => 'Действия', 'width' => '100px'],
|
||||
'actionsConfig' => [
|
||||
[
|
||||
'label' => '',
|
||||
'url' => '/superadmin/subscriptions/delete/{id}',
|
||||
'icon' => 'fa-solid fa-trash',
|
||||
'class' => 'btn-outline-danger',
|
||||
'title' => 'Удалить',
|
||||
'confirm' => 'Удалить подписку?',
|
||||
],
|
||||
],
|
||||
'emptyMessage' => 'Подписки не найдены',
|
||||
'emptyIcon' => 'fa-solid fa-credit-card',
|
||||
];
|
||||
|
||||
if (!$this->planModel->insert($data)) {
|
||||
return redirect()->back()->withInput()->with('error', 'Ошибка создания тарифа: ' . implode(', ', $this->planModel->errors()));
|
||||
}
|
||||
|
||||
return redirect()->to('/superadmin/plans')->with('success', 'Тариф успешно создан');
|
||||
}
|
||||
|
||||
/**
|
||||
* Редактирование тарифа (форма)
|
||||
* Список подписок
|
||||
*/
|
||||
public function editPlan($id)
|
||||
public function subscriptions()
|
||||
{
|
||||
$plan = $this->planModel->find($id);
|
||||
if (!$plan) {
|
||||
throw new \CodeIgniter\Exceptions\PageNotFoundException('Тариф не найден');
|
||||
}
|
||||
$config = $this->getSubscriptionsTableConfig();
|
||||
$tableHtml = $this->renderTable($config);
|
||||
$modules = $this->subscriptionService->getAllModules();
|
||||
$organizations = $this->organizationModel->findAll();
|
||||
|
||||
// Декодируем features для отображения в textarea
|
||||
$plan['features'] = json_decode($plan['features'] ?? '[]', true);
|
||||
|
||||
return $this->renderTwig('superadmin/plans/edit', compact('plan'));
|
||||
return $this->renderTwig('superadmin/subscriptions/index', [
|
||||
'tableHtml' => $tableHtml,
|
||||
'config' => $config,
|
||||
'modules' => $modules,
|
||||
'organizations' => $organizations,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновление тарифа
|
||||
* AJAX таблица подписок
|
||||
*/
|
||||
public function updatePlan($id)
|
||||
public function subscriptionsTable()
|
||||
{
|
||||
// Получаем features из текстового поля (каждая строка - отдельная возможность)
|
||||
$featuresText = $this->request->getPost('features_list');
|
||||
$features = [];
|
||||
if ($featuresText) {
|
||||
$lines = explode("\n", trim($featuresText));
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
$features[] = $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->request->getPost('name'),
|
||||
'description' => $this->request->getPost('description'),
|
||||
'price' => (float) $this->request->getPost('price'),
|
||||
'currency' => $this->request->getPost('currency') ?? 'RUB',
|
||||
'billing_period' => $this->request->getPost('billing_period') ?? 'monthly',
|
||||
'max_users' => (int) $this->request->getPost('max_users'),
|
||||
'max_clients' => (int) $this->request->getPost('max_clients'),
|
||||
'max_storage' => (int) $this->request->getPost('max_storage'),
|
||||
'features' => json_encode($features),
|
||||
'is_active' => $this->request->getPost('is_active') ?? 1,
|
||||
'is_default' => $this->request->getPost('is_default') ?? 0,
|
||||
];
|
||||
|
||||
if (!$this->planModel->update($id, $data)) {
|
||||
return redirect()->back()->withInput()->with('error', 'Ошибка обновления тарифа: ' . implode(', ', $this->planModel->errors()));
|
||||
}
|
||||
|
||||
return redirect()->to('/superadmin/plans')->with('success', 'Тариф успешно обновлён');
|
||||
return parent::table($this->getSubscriptionsTableConfig(), '/superadmin/subscriptions');
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление тарифа
|
||||
* Поиск организаций для autocomplete
|
||||
*/
|
||||
public function deletePlan($id)
|
||||
public function searchOrganizations()
|
||||
{
|
||||
if (!$this->planModel->delete($id)) {
|
||||
return redirect()->to('/superadmin/plans')->with('error', 'Ошибка удаления тарифа');
|
||||
$query = $this->request->getGet('q') ?? '';
|
||||
$limit = 20;
|
||||
|
||||
$builder = $this->organizationModel->db()->table('organizations');
|
||||
|
||||
$builder->select('organizations.*, users.email as owner_email')
|
||||
->join('organization_users', 'organization_users.organization_id = organizations.id AND organization_users.role = "owner"')
|
||||
->join('users', 'users.id = organization_users.user_id')
|
||||
->groupStart()
|
||||
->like('organizations.name', $query)
|
||||
->orLike('organizations.id', $query)
|
||||
->orLike('users.email', $query)
|
||||
->groupEnd()
|
||||
->limit($limit);
|
||||
|
||||
$results = [];
|
||||
foreach ($builder->get()->getResultArray() as $org) {
|
||||
$results[] = [
|
||||
'id' => $org['id'],
|
||||
'text' => $org['name'] . ' (ID: ' . $org['id'] . ') — ' . $org['owner_email'],
|
||||
];
|
||||
}
|
||||
|
||||
return redirect()->to('/superadmin/plans')->with('success', 'Тариф успешно удалён');
|
||||
return $this->response->setJSON(['results' => $results]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление подписки (форма)
|
||||
*/
|
||||
public function createSubscription()
|
||||
{
|
||||
$organizations = $this->organizationModel->findAll();
|
||||
$modules = $this->subscriptionService->getAllModules();
|
||||
|
||||
return $this->renderTwig('superadmin/subscriptions/create', compact('organizations', 'modules'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранение подписки
|
||||
*/
|
||||
public function storeSubscription()
|
||||
{
|
||||
$organizationId = (int) $this->request->getPost('organization_id');
|
||||
$moduleCode = $this->request->getPost('module_code');
|
||||
$durationDays = (int) $this->request->getPost('duration_days');
|
||||
$status = $this->request->getPost('status') ?? 'active';
|
||||
|
||||
// Валидация
|
||||
$organization = $this->organizationModel->find($organizationId);
|
||||
if (!$organization) {
|
||||
return redirect()->back()->withInput()->with('error', 'Организация не найдена');
|
||||
}
|
||||
|
||||
$moduleConfig = $this->subscriptionService->getModuleConfig($moduleCode);
|
||||
if (!$moduleCode || !$moduleConfig) {
|
||||
return redirect()->back()->withInput()->with('error', 'Модуль не найден');
|
||||
}
|
||||
|
||||
$this->subscriptionService->upsertSubscription(
|
||||
$organizationId,
|
||||
$moduleCode,
|
||||
$status,
|
||||
$durationDays
|
||||
);
|
||||
|
||||
return redirect()->to('/superadmin/subscriptions')->with('success', 'Подписка создана');
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление подписки
|
||||
*/
|
||||
public function deleteSubscription($id)
|
||||
{
|
||||
$this->subscriptionService->deleteSubscription($id);
|
||||
|
||||
return redirect()->to('/superadmin/subscriptions')->with('success', 'Подписка удалена');
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
@@ -194,19 +269,23 @@ class Superadmin extends BaseController
|
||||
'columns' => [
|
||||
'id' => ['label' => 'ID', 'width' => '60px'],
|
||||
'name' => ['label' => 'Название'],
|
||||
'owner_login' => ['label' => 'Владелец', 'width' => '150px'],
|
||||
'type' => ['label' => 'Тип', 'width' => '100px'],
|
||||
'user_count' => ['label' => 'Пользователей', 'width' => '100px'],
|
||||
'status' => ['label' => 'Статус', 'width' => '120px'],
|
||||
'created_at' => ['label' => 'Дата', 'width' => '100px'],
|
||||
],
|
||||
'searchable' => ['name', 'id'],
|
||||
'searchable' => ['name', 'id', 'owner_login'],
|
||||
'sortable' => ['id', 'name', 'created_at'],
|
||||
'defaultSort' => 'created_at',
|
||||
'order' => 'desc',
|
||||
'scope' => function ($builder) {
|
||||
// JOIN с подсчётом пользователей организации
|
||||
$builder->from('organizations')
|
||||
->select('organizations.*, (SELECT COUNT(*) FROM organization_users WHERE organization_users.organization_id = organizations.id AND status = "active") as user_count');
|
||||
$builder->resetQuery();
|
||||
$builder->select('organizations.*,
|
||||
(SELECT COUNT(*) FROM organization_users WHERE organization_users.organization_id = organizations.id AND status = "active") as user_count,
|
||||
owner_users.email as owner_login')
|
||||
->join('organization_users as ou', 'ou.organization_id = organizations.id AND ou.role = "owner"')
|
||||
->join('users as owner_users', 'owner_users.id = ou.user_id', 'left');
|
||||
},
|
||||
'actions' => ['label' => 'Действия', 'width' => '140px'],
|
||||
'actionsConfig' => [
|
||||
@@ -263,7 +342,7 @@ class Superadmin extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Просмотр организации
|
||||
* Просмотр организации с её подписками
|
||||
*/
|
||||
public function viewOrganization($id)
|
||||
{
|
||||
@@ -272,23 +351,49 @@ class Superadmin extends BaseController
|
||||
throw new \CodeIgniter\Exceptions\PageNotFoundException('Организация не найдена');
|
||||
}
|
||||
|
||||
// Пользователи организации
|
||||
$orgUserModel = new \App\Models\OrganizationUserModel();
|
||||
$users = $orgUserModel->getOrganizationUsers($id);
|
||||
$users = $this->getOrgUserModel()->getOrganizationUsers($id);
|
||||
$subscriptions = $this->subscriptionService->getOrganizationSubscriptions($id);
|
||||
$allModules = $this->subscriptionService->getAllModules();
|
||||
|
||||
// Список тарифов для выбора
|
||||
$plans = $this->planModel->where('is_active', 1)->findAll();
|
||||
return $this->renderTwig('superadmin/organizations/view', compact(
|
||||
'organization',
|
||||
'users',
|
||||
'subscriptions',
|
||||
'allModules'
|
||||
));
|
||||
}
|
||||
|
||||
// Текущая подписка организации из таблицы связей
|
||||
$db = \Config\Database::connect();
|
||||
$subscriptionTable = $db->table('organization_plan_subscriptions');
|
||||
$currentSubscription = $subscriptionTable
|
||||
->where('organization_id', $id)
|
||||
->orderBy('id', 'DESC')
|
||||
->get()
|
||||
->getRowArray();
|
||||
/**
|
||||
* Быстрое добавление подписки организации из просмотра организации
|
||||
*/
|
||||
public function addOrganizationSubscription($organizationId)
|
||||
{
|
||||
$moduleCode = $this->request->getPost('module_code');
|
||||
$durationDays = (int) $this->request->getPost('duration_days');
|
||||
$status = $this->request->getPost('status') ?? 'active';
|
||||
|
||||
return $this->renderTwig('superadmin/organizations/view', compact('organization', 'users', 'plans', 'currentSubscription'));
|
||||
if (!$moduleCode) {
|
||||
return redirect()->back()->with('error', 'Модуль не выбран');
|
||||
}
|
||||
|
||||
$this->subscriptionService->upsertSubscription(
|
||||
$organizationId,
|
||||
$moduleCode,
|
||||
$status,
|
||||
$durationDays
|
||||
);
|
||||
|
||||
return redirect()->to("/superadmin/organizations/view/{$organizationId}")->with('success', 'Подписка добавлена');
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление подписки организации
|
||||
*/
|
||||
public function removeOrganizationSubscription($organizationId, $subscriptionId)
|
||||
{
|
||||
$this->subscriptionService->deleteSubscription($subscriptionId);
|
||||
|
||||
return redirect()->to("/superadmin/organizations/view/{$organizationId}")->with('success', 'Подписка удалена');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,72 +417,15 @@ class Superadmin extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление организации (полное удаление)
|
||||
* Удаление организации
|
||||
*/
|
||||
public function deleteOrganization($id)
|
||||
{
|
||||
// Полное удаление без soft delete
|
||||
$this->organizationModel->delete($id, true);
|
||||
|
||||
return redirect()->to('/superadmin/organizations')->with('success', 'Организация удалена');
|
||||
}
|
||||
|
||||
/**
|
||||
* Назначение тарифа организации
|
||||
*/
|
||||
public function setOrganizationPlan($id)
|
||||
{
|
||||
$planId = $this->request->getPost('plan_id');
|
||||
$durationDays = (int) $this->request->getPost('duration_days');
|
||||
|
||||
if (!$planId) {
|
||||
return redirect()->back()->with('error', 'Выберите тариф');
|
||||
}
|
||||
|
||||
$plan = $this->planModel->find($planId);
|
||||
if (!$plan) {
|
||||
return redirect()->back()->with('error', 'Тариф не найден');
|
||||
}
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$subscriptionsTable = $db->table('organization_plan_subscriptions');
|
||||
|
||||
$startDate = date('Y-m-d H:i:s');
|
||||
$endDate = $durationDays > 0
|
||||
? date('Y-m-d H:i:s', strtotime("+{$durationDays} days"))
|
||||
: null;
|
||||
|
||||
// Проверяем существующую подписку
|
||||
$existingSub = $subscriptionsTable
|
||||
->where('organization_id', $id)
|
||||
->where('plan_id', $planId)
|
||||
->get()
|
||||
->getRowArray();
|
||||
|
||||
if ($existingSub) {
|
||||
// Обновляем существующую подписку
|
||||
$subscriptionsTable->where('id', $existingSub['id'])->update([
|
||||
'status' => $durationDays > 0 ? 'active' : 'trial',
|
||||
'trial_ends_at' => $endDate,
|
||||
'expires_at' => $endDate,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
} else {
|
||||
// Создаём новую подписку
|
||||
$subscriptionsTable->insert([
|
||||
'organization_id' => $id,
|
||||
'plan_id' => $planId,
|
||||
'status' => $durationDays > 0 ? 'active' : 'trial',
|
||||
'trial_ends_at' => $endDate,
|
||||
'expires_at' => $endDate,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->to("/superadmin/organizations/view/{$id}")->with('success', 'Тариф успешно назначен');
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// УПРАВЛЕНИЕ ПОЛЬЗОВАТЕЛЯМИ
|
||||
// =========================================================================
|
||||
@@ -405,7 +453,6 @@ class Superadmin extends BaseController
|
||||
'defaultSort' => 'created_at',
|
||||
'order' => 'desc',
|
||||
'scope' => function ($builder) {
|
||||
// JOIN с подсчётом организаций пользователя
|
||||
$builder->from('users')
|
||||
->select('users.*, (SELECT COUNT(*) FROM organization_users WHERE organization_users.user_id = users.id) as org_count');
|
||||
},
|
||||
@@ -494,11 +541,10 @@ class Superadmin extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление пользователя (полное удаление)
|
||||
* Удаление пользователя
|
||||
*/
|
||||
public function deleteUser($id)
|
||||
{
|
||||
// Полное удаление без soft delete
|
||||
$this->userModel->delete($id, true);
|
||||
|
||||
return redirect()->to('/superadmin/users')->with('success', 'Пользователь удалён');
|
||||
@@ -513,7 +559,6 @@ class Superadmin extends BaseController
|
||||
*/
|
||||
public function statistics()
|
||||
{
|
||||
// Статистика по дням (последние 30 дней)
|
||||
$dailyStats = [];
|
||||
for ($i = 29; $i >= 0; $i--) {
|
||||
$date = date('Y-m-d', strtotime("-{$i} days"));
|
||||
@@ -524,35 +569,8 @@ class Superadmin extends BaseController
|
||||
];
|
||||
}
|
||||
|
||||
// Статистика по тарифам (через таблицу подписок)
|
||||
$planStats = [];
|
||||
$plans = $this->planModel->where('is_active', 1)->findAll();
|
||||
$moduleStats = $this->subscriptionService->getModuleStats();
|
||||
|
||||
// Проверяем существование таблицы подписок
|
||||
$db = \Config\Database::connect();
|
||||
$tableExists = $db->tableExists('organization_plan_subscriptions');
|
||||
|
||||
if ($tableExists) {
|
||||
$subscriptionsTable = $db->table('organization_plan_subscriptions');
|
||||
foreach ($plans as $plan) {
|
||||
$count = $subscriptionsTable->where('plan_id', $plan['id'])
|
||||
->where('status', 'active')
|
||||
->countAllResults();
|
||||
$planStats[$plan['id']] = [
|
||||
'name' => $plan['name'],
|
||||
'orgs_count' => $count,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// Таблица подписок ещё не создана - показываем 0 для всех тарифов
|
||||
foreach ($plans as $plan) {
|
||||
$planStats[$plan['id']] = [
|
||||
'name' => $plan['name'],
|
||||
'orgs_count' => 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderTwig('superadmin/statistics', compact('dailyStats', 'planStats'));
|
||||
return $this->renderTwig('superadmin/statistics', compact('dailyStats', 'moduleStats'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user