This commit is contained in:
F4ilji
2026-04-07 17:54:26 +05:00
parent 04adba6682
commit 936b1fb5b0
468 changed files with 43498 additions and 4176 deletions
@@ -0,0 +1,21 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\InstituteStructure\Models\Department;
use App\Services\App\Cache\DepartmentCacheService;
class AttachDepartmentProgramAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, EducationalProgram $program): void
{
$department->programs()->attach($program->id);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class AttachDepartmentTeacherAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user, array $data): void
{
$department->teachers()->attach($user->id, [
'teaching_position' => $data['teaching_position'],
'service_email' => $data['service_email'] ?? null,
'service_phone' => $data['service_phone'] ?? null,
'cabinet' => $data['cabinet'] ?? null,
'sort' => $department->teachers()->count() + 1,
]);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class AttachDepartmentWorkerAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user, array $data): void
{
$department->workers()->attach($user->id, [
'position' => $data['position'],
'service_email' => $data['service_email'] ?? null,
'service_phone' => $data['service_phone'] ?? null,
'cabinet' => $data['cabinet'] ?? null,
'sort' => $department->workers()->count() + 1,
]);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\Dashboard\Tasks\Content\GenerateSearchDataTask;
use App\Containers\InstituteStructure\Models\Department;
use Illuminate\Support\Str;
class CreateDepartmentAction
{
public function __construct(
private readonly GenerateSearchDataTask $generateSearchDataTask,
) {}
public function run(array $data): Department
{
// Генерируем slug если не передан
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
// Генерируем search_data из контента
if (!empty($data['content'])) {
$data['search_data'] = $this->generateSearchDataTask->run($data['content']);
}
$department = Department::create($data);
// Создаем SEO
$this->generateSeo($department, $data);
return $department;
}
private function generateSeo(Department $department, array $data): void
{
$title = $data['title'] ?? '';
$description = null;
// Извлекаем description из первого paragraph блока
if (!empty($data['content'])) {
foreach ($data['content'] as $block) {
if ($block['type'] === 'paragraph') {
$description = strip_tags($block['data']['content']);
break;
}
}
}
$department->seo()->create([
'title' => $title,
'description' => Str::limit(htmlspecialchars($description ?? '', ENT_QUOTES, 'UTF-8'), 160),
]);
}
}
@@ -0,0 +1,13 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
class DeleteDepartmentAction
{
public function run(Department $department): void
{
$department->delete();
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\InstituteStructure\Models\Department;
use App\Services\App\Cache\DepartmentCacheService;
class DetachDepartmentProgramAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, EducationalProgram $program): void
{
$department->programs()->detach($program->id);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class DetachDepartmentTeacherAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user): void
{
$department->teachers()->detach($user->id);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class DetachDepartmentWorkerAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user): void
{
$department->workers()->detach($user->id);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Services\App\Cache\DepartmentCacheService;
class ListDepartmentProgramsAction
{
public function run(Department $department, array $filters = []): array
{
$query = $department->programs();
// Фильтр по статусу
if (!empty($filters['status'])) {
$query->where('status', $filters['status']);
}
// Поиск по названию
if (!empty($filters['search'])) {
$query->where('name', 'like', '%' . $filters['search'] . '%');
}
$programs = $query->orderBy('name')->paginate(20)->withQueryString();
return [
'programs' => $programs,
'filters' => $filters,
];
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
class ListDepartmentTeachersAction
{
public function run(Department $department, array $filters = []): array
{
$query = $department->teachers();
// Поиск по имени
if (!empty($filters['search'])) {
$query->where('name', 'like', '%' . $filters['search'] . '%');
}
// Фильтр по должности
if (!empty($filters['position'])) {
$query->where('teaching_position', 'like', '%' . $filters['position'] . '%');
}
$teachers = $query->orderBy('teachers_departments.sort')->paginate(20)->withQueryString();
return [
'teachers' => $teachers,
'filters' => $filters,
];
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
class ListDepartmentWorkersAction
{
public function run(Department $department, array $filters = []): array
{
$query = $department->workers();
// Поиск по имени
if (!empty($filters['search'])) {
$query->where('name', 'like', '%' . $filters['search'] . '%');
}
// Фильтр по должности
if (!empty($filters['position'])) {
$query->where('position', 'like', '%' . $filters['position'] . '%');
}
$workers = $query->orderBy('workers_departments.sort')->paginate(20)->withQueryString();
return [
'workers' => $workers,
'filters' => $filters,
];
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
class ListDepartmentsAction
{
public function run(array $filters = []): array
{
$query = Department::query()->with(['faculty']);
// Фильтр по факультету
if (isset($filters['faculty_id']) && $filters['faculty_id'] !== '') {
$query->where('faculty_id', (int) $filters['faculty_id']);
}
// Фильтр по статусу
if (isset($filters['is_active']) && $filters['is_active'] !== '') {
$query->where('is_active', (bool) $filters['is_active']);
}
// Поиск по названию
if (!empty($filters['search'])) {
$query->where('title', 'like', '%' . $filters['search'] . '%');
}
$departments = $query->orderBy('title')->paginate(20)->withQueryString();
return [
'departments' => $departments,
'filters' => $filters,
];
}
}
@@ -0,0 +1,56 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\Dashboard\Tasks\Content\GenerateSearchDataTask;
use App\Containers\InstituteStructure\Models\Department;
use Illuminate\Support\Str;
class UpdateDepartmentAction
{
public function __construct(
private readonly GenerateSearchDataTask $generateSearchDataTask,
) {}
public function run(Department $department, array $data): Department
{
// Генерируем search_data из контента только если контент передан и не пуст
if (isset($data['content']) && !empty($data['content'])) {
$data['search_data'] = $this->generateSearchDataTask->run($data['content']);
}
$department->update($data);
// Обновляем SEO
$this->updateSeo($department, $data);
return $department;
}
private function updateSeo(Department $department, array $data): void
{
$title = $data['title'] ?? $department->title;
$description = null;
// Извлекаем description из первого paragraph блока
if (!empty($data['content'])) {
foreach ($data['content'] as $block) {
if ($block['type'] === 'paragraph') {
$description = strip_tags($block['data']['content']);
break;
}
}
}
$seoData = [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description ?? '', ENT_QUOTES, 'UTF-8'), 160),
];
if ($department->seo) {
$department->seo->update($seoData);
} else {
$department->seo()->create($seoData);
}
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class UpdateDepartmentTeacherAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user, array $data): void
{
$department->teachers()->updateExistingPivot($user->id, [
'teaching_position' => $data['teaching_position'],
'service_email' => $data['service_email'] ?? null,
'service_phone' => $data['service_phone'] ?? null,
'cabinet' => $data['cabinet'] ?? null,
]);
$this->cacheService->clearAllCacheByModel();
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Dashboard\Actions\Departments;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Services\App\Cache\DepartmentCacheService;
class UpdateDepartmentWorkerAction
{
public function __construct(
private readonly DepartmentCacheService $cacheService,
) {}
public function run(Department $department, User $user, array $data): void
{
$department->workers()->updateExistingPivot($user->id, [
'position' => $data['position'],
'service_email' => $data['service_email'] ?? null,
'service_phone' => $data['service_phone'] ?? null,
'cabinet' => $data['cabinet'] ?? null,
]);
$this->cacheService->clearAllCacheByModel();
}
}