added API VICON integration for updating admission plans via admin panel (queued).
Updated exams and contests display on programs/show page. Added relevant enums for admission plans.
This commit is contained in:
@@ -7,13 +7,31 @@ use Filament\Support\Contracts\HasColor;
|
||||
|
||||
enum BudgetEducation: int implements HasLabel, HasColor
|
||||
{
|
||||
case budget_quantity_position = 1;
|
||||
case non_budget_quantity_position = 2;
|
||||
case MAIN_QUOTA = 1;
|
||||
case TARGET_QUOTA = 2;
|
||||
case SPECIAL_QUOTA = 3;
|
||||
case PAID_EDUCATION = 4;
|
||||
case OTHER_SOURCES = 5;
|
||||
case SEPARATE_QUOTA = 6;
|
||||
case COMBINED_QUOTA_ALL = 7;
|
||||
case COMBINED_QUOTA_TARGET_SPECIAL = 8;
|
||||
case COMBINED_QUOTA_TARGET_SEPARATE = 9;
|
||||
case COMBINED_QUOTA_SPECIAL_SEPARATE = 10;
|
||||
case DETAILED_TARGET_QUOTA = 11;
|
||||
|
||||
public static function fromName(string $name): ?self {
|
||||
return match ($name) {
|
||||
'budget_quantity_position' => self::budget_quantity_position,
|
||||
'non_budget_quantity_position' => self::non_budget_quantity_position,
|
||||
'MAIN_QUOTA' => self::MAIN_QUOTA,
|
||||
'TARGET_QUOTA' => self::TARGET_QUOTA,
|
||||
'SPECIAL_QUOTA' => self::SPECIAL_QUOTA,
|
||||
'PAID_EDUCATION' => self::PAID_EDUCATION,
|
||||
'OTHER_SOURCES' => self::OTHER_SOURCES,
|
||||
'SEPARATE_QUOTA' => self::SEPARATE_QUOTA,
|
||||
'COMBINED_QUOTA_ALL' => self::COMBINED_QUOTA_ALL,
|
||||
'COMBINED_QUOTA_TARGET_SPECIAL' => self::COMBINED_QUOTA_TARGET_SPECIAL,
|
||||
'COMBINED_QUOTA_TARGET_SEPARATE' => self::COMBINED_QUOTA_TARGET_SEPARATE,
|
||||
'COMBINED_QUOTA_SPECIAL_SEPARATE' => self::COMBINED_QUOTA_SPECIAL_SEPARATE,
|
||||
'DETAILED_TARGET_QUOTA' => self::DETAILED_TARGET_QUOTA,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
@@ -21,16 +39,34 @@ enum BudgetEducation: int implements HasLabel, HasColor
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
return match ($this) {
|
||||
self::budget_quantity_position => 'Бюджетные места',
|
||||
self::non_budget_quantity_position => 'С оплатой обучения',
|
||||
self::MAIN_QUOTA => 'Основные места',
|
||||
self::TARGET_QUOTA => 'Целевая квота',
|
||||
self::SPECIAL_QUOTA => 'Особая квота',
|
||||
self::PAID_EDUCATION => 'С оплатой обучения',
|
||||
self::OTHER_SOURCES => 'За счёт иных средств',
|
||||
self::SEPARATE_QUOTA => 'Отдельная квота',
|
||||
self::COMBINED_QUOTA_ALL => 'Совмещенная квота (целевая, особая и отдельная квоты)',
|
||||
self::COMBINED_QUOTA_TARGET_SPECIAL => 'Совмещенная квота (целевая и особая квоты)',
|
||||
self::COMBINED_QUOTA_TARGET_SEPARATE => 'Совмещенная квота (целевая и отдельная квоты)',
|
||||
self::COMBINED_QUOTA_SPECIAL_SEPARATE => 'Совмещенная квота (особая и отдельная квоты)',
|
||||
self::DETAILED_TARGET_QUOTA => 'Детализированная целевая квота',
|
||||
};
|
||||
}
|
||||
|
||||
public function getColor(): string|array|null
|
||||
{
|
||||
return match ($this) {
|
||||
self::budget_quantity_position => 'success', // Цвет для очной формы
|
||||
self::non_budget_quantity_position => 'warning', // Цвет для заочной формы
|
||||
self::MAIN_QUOTA => 'primary',
|
||||
self::TARGET_QUOTA => 'info',
|
||||
self::SPECIAL_QUOTA => 'danger',
|
||||
self::PAID_EDUCATION => 'warning',
|
||||
self::OTHER_SOURCES => 'gray',
|
||||
self::SEPARATE_QUOTA => 'success',
|
||||
self::COMBINED_QUOTA_ALL => 'indigo',
|
||||
self::COMBINED_QUOTA_TARGET_SPECIAL => 'violet',
|
||||
self::COMBINED_QUOTA_TARGET_SEPARATE => 'fuchsia',
|
||||
self::COMBINED_QUOTA_SPECIAL_SEPARATE => 'pink',
|
||||
self::DETAILED_TARGET_QUOTA => 'amber',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,18 @@ use Filament\Support\Contracts\HasColor;
|
||||
enum FormEducation: int implements HasLabel, HasColor
|
||||
{
|
||||
case FULL_TIME = 1; // Очная форма обучения
|
||||
case PART_TIME = 2; // Заочная форма обучения
|
||||
|
||||
case FULL_PART_TIME = 3; // Заочная форма обучения
|
||||
case FULL_PART_TIME = 2; // Заочная форма обучения
|
||||
|
||||
case PART_TIME = 3; // Заочная форма обучения
|
||||
|
||||
|
||||
|
||||
public static function fromName(string $name): ?self {
|
||||
return match ($name) {
|
||||
'FULL_TIME' => self::FULL_TIME,
|
||||
'PART_TIME' => self::PART_TIME,
|
||||
'FULL_PART_TIME' => self::FULL_PART_TIME,
|
||||
'PART_TIME' => self::PART_TIME,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
@@ -26,8 +28,8 @@ enum FormEducation: int implements HasLabel, HasColor
|
||||
{
|
||||
return match ($this) {
|
||||
self::FULL_TIME => 'Очная форма обучения',
|
||||
self::FULL_PART_TIME => 'Очно-заочная форма обучения',
|
||||
self::PART_TIME => 'Заочная форма обучения',
|
||||
self::FULL_PART_TIME => 'Очно-заочная форма обучения'
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Filament\Support\Contracts\HasLabel;
|
||||
use Filament\Support\Contracts\HasColor;
|
||||
|
||||
enum TypeExam: int implements HasLabel, HasColor
|
||||
{
|
||||
case EGE = 1;
|
||||
case INTERNAL_EXAM = 2;
|
||||
case AVG_SCORE = 3;
|
||||
case ACCREDITATION = 4;
|
||||
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
return match ($this) {
|
||||
self::EGE => 'ЕГЭ',
|
||||
self::INTERNAL_EXAM => 'ВИ, проводимое организацией самостоятельно',
|
||||
self::AVG_SCORE => 'Ср. балл документа об образовании',
|
||||
self::ACCREDITATION => 'Аккредитация',
|
||||
};
|
||||
}
|
||||
|
||||
public function getColor(): string|array|null
|
||||
{
|
||||
return match ($this) {
|
||||
self::EGE => 'primary',
|
||||
self::INTERNAL_EXAM => 'info',
|
||||
self::AVG_SCORE => 'success',
|
||||
self::ACCREDITATION => 'warning',
|
||||
};
|
||||
}
|
||||
|
||||
public static function fromName(string $name): ?self
|
||||
{
|
||||
return match ($name) {
|
||||
'EGE' => self::EGE,
|
||||
'INTERNAL_EXAM' => self::INTERNAL_EXAM,
|
||||
'AVG_SCORE' => self::AVG_SCORE,
|
||||
'ACCREDITATION' => self::ACCREDITATION,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -22,32 +22,32 @@ class ListAdmissionCampaigns extends ListRecords
|
||||
->action(function () {
|
||||
// Отправляем запрос в фоновом режиме
|
||||
$this->js(<<<JS
|
||||
fetch('/api/get-data', {
|
||||
fetch('/api/get-edu-program-data', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
},
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
.then(() => {
|
||||
// Показываем уведомление об успешном завершении
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'success',
|
||||
title: 'Данные обновлены',
|
||||
body: 'Данные успешно обновлены.',
|
||||
},
|
||||
body: 'Данные успешно обновлены.'
|
||||
}
|
||||
}));
|
||||
})
|
||||
.catch(error => {
|
||||
.catch(() => {
|
||||
// Показываем уведомление об ошибке
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'danger',
|
||||
title: 'Ошибка',
|
||||
body: 'Произошла ошибка при обновлении данных.',
|
||||
},
|
||||
body: 'Произошла ошибка при обновлении данных.'
|
||||
}
|
||||
}));
|
||||
});
|
||||
JS);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Filament\Resources;
|
||||
use App\Enums\BudgetEducation;
|
||||
use App\Enums\EducationalProgramStatus;
|
||||
use App\Enums\FormEducation;
|
||||
use App\Enums\TypeExam;
|
||||
use App\Filament\Resources\AdmissionPlanResource\Pages;
|
||||
use App\Models\AdmissionCampaign;
|
||||
use App\Models\AdmissionPlan;
|
||||
@@ -82,20 +83,23 @@ class AdmissionPlanResource extends Resource
|
||||
->maxLength(100)
|
||||
->placeholder('Например: Математика')
|
||||
->helperText('Название вступительного испытания'),
|
||||
TextInput::make('priority')
|
||||
->label('Приоритет предмета')
|
||||
->required()
|
||||
->numeric()
|
||||
->columnSpanFull()
|
||||
->maxLength(10),
|
||||
|
||||
Repeater::make('exam')->schema([
|
||||
Select::make('type_exam')
|
||||
Repeater::make('types')->schema([
|
||||
Select::make('type')
|
||||
->label('Тип испытания')
|
||||
->required()
|
||||
->options([
|
||||
'ege' => 'ЕГЭ',
|
||||
'internal_test' => 'Внутреннее испытание',
|
||||
])
|
||||
->options(TypeExam::class)
|
||||
->native(false)
|
||||
->placeholder('Выберите тип')
|
||||
->helperText('Тип вступительного испытания'),
|
||||
|
||||
TextInput::make('min_score')
|
||||
TextInput::make('min_ball')
|
||||
->label('Минимальный балл')
|
||||
->required()
|
||||
->numeric()
|
||||
@@ -134,38 +138,33 @@ class AdmissionPlanResource extends Resource
|
||||
->placeholder('Выберите форму')
|
||||
->columnSpanFull()
|
||||
->helperText('Форма обучения для данной группы'),
|
||||
Section::make()->schema([
|
||||
Select::make('places.form_budget')
|
||||
->label('Форма финансирования')
|
||||
->options(BudgetEducation::class)
|
||||
->required()
|
||||
->native(false)
|
||||
->placeholder('Выберите тип')
|
||||
->helperText('Бюджетные или платные места'),
|
||||
|
||||
Repeater::make('places')
|
||||
->label('Места')
|
||||
->schema([
|
||||
Select::make('form_budget')
|
||||
->label('Форма финансирования')
|
||||
->options(BudgetEducation::class)
|
||||
->required()
|
||||
->native(false)
|
||||
->placeholder('Выберите тип')
|
||||
->helperText('Бюджетные или платные места'),
|
||||
|
||||
TextInput::make('count')
|
||||
->label('Количество мест')
|
||||
->required()
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->placeholder('Укажите количество')
|
||||
->helperText('Количество доступных мест'),
|
||||
])
|
||||
->columnSpanFull()
|
||||
->maxItems(2)
|
||||
->addActionLabel('Добавить тип мест')
|
||||
TextInput::make('places.count')
|
||||
->label('Количество мест')
|
||||
->required()
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->placeholder('Укажите количество')
|
||||
->helperText('Количество доступных мест'),
|
||||
]),
|
||||
])
|
||||
->columns(2)
|
||||
->maxItems(3)
|
||||
->maxItems(4) // Adjust if needed based on your actual requirements
|
||||
->collapsible()
|
||||
->collapsed()
|
||||
->addActionLabel('Добавить группу')
|
||||
->helperText('Добавьте группы с условиями поступления');
|
||||
}
|
||||
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
@@ -187,6 +186,9 @@ class AdmissionPlanResource extends Resource
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Filament\Resources\AdmissionPlanResource\Pages;
|
||||
|
||||
use App\Filament\Resources\AdmissionPlanResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListAdmissionPlans extends ListRecords
|
||||
@@ -13,7 +14,52 @@ class ListAdmissionPlans extends ListRecords
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
Actions\CreateAction::make(), // Стандартная кнопка "Создать"
|
||||
Actions\Action::make('fetchData') // Кастомная кнопка
|
||||
->label('Обновить данные')
|
||||
->color('primary') // Цвет кнопки
|
||||
->icon('heroicon-o-arrow-path') // Иконка
|
||||
->action(function () {
|
||||
// Отправляем запрос в фоновом режиме
|
||||
$this->js(<<<JS
|
||||
fetch('/api/get-admission-plans-data', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(() => {
|
||||
// Показываем уведомление об успешном завершении
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'success',
|
||||
title: 'Данные обновлены',
|
||||
body: 'Данные успешно обновлены.'
|
||||
}
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
// Показываем уведомление об ошибке
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'danger',
|
||||
title: 'Ошибка',
|
||||
body: 'Произошла ошибка при обновлении данных.'
|
||||
}
|
||||
}));
|
||||
});
|
||||
JS);
|
||||
|
||||
// Показываем уведомление
|
||||
Notification::make()
|
||||
->title('Данные обновляются')
|
||||
->body('Данные обновляются в фоновом режиме.')
|
||||
->success()
|
||||
->send();
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class IconController extends Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Jobs\CreateAdmissionPlan;
|
||||
use App\Jobs\CreateDirectionStudy;
|
||||
use App\Jobs\CreateEducationalProgram;
|
||||
use App\Services\Vicon\EducationalProgram\EducationalProgramService;
|
||||
|
||||
class UpdateAdmissionPlansDataApiController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->clearAndCreateAdmissionPlans();
|
||||
return redirect()->route('index');
|
||||
}
|
||||
|
||||
private function clearAndCreateAdmissionPlans() : void
|
||||
{
|
||||
dispatch(new CreateAdmissionPlan());
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,6 @@ use App\Services\Vicon\EducationalProgram\EducationalProgramService;
|
||||
|
||||
class UpdateEduDataApiController extends Controller
|
||||
{
|
||||
private $programService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->programService = new EducationalProgramService();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Enums\LevelEducational;
|
||||
use App\Models\AdmissionCampaign;
|
||||
use App\Models\DirectionStudy;
|
||||
use App\Models\EducationalProgram;
|
||||
use App\Services\Vicon\DirectionStudy\AdmissionPlanService;
|
||||
use App\Services\Vicon\EducationalProgram\EducationalProgramService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CreateAdmissionPlan implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
|
||||
private AdmissionPlanService $admissionPlanService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->admissionPlanService = app(AdmissionPlanService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
$items = $this->admissionPlanService->getCampaigns();
|
||||
|
||||
if (empty($items)) {
|
||||
Log::warning('Empty campaigns list received');
|
||||
return; // или обработка пустого случая
|
||||
}
|
||||
|
||||
$campaign = $this->admissionPlanService->findActiveCampaign($items);
|
||||
|
||||
if (empty($campaign)) {
|
||||
Log::warning('No active campaign found in the list');
|
||||
return;
|
||||
}
|
||||
|
||||
$levels_codes = $this->admissionPlanService->getLevelEducationCodes($campaign);
|
||||
|
||||
if (empty($levels_codes)) {
|
||||
Log::warning('No education level codes found for campaign');
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($levels_codes as $code) {
|
||||
$admissionPlans = $this->admissionPlanService->getAdmissionPlans($code);
|
||||
|
||||
// Проверка на пустой результат или отсутствие нужного свойства
|
||||
if (empty($admissionPlans) || !isset($admissionPlans->competitons_groups)) {
|
||||
Log::warning("Empty admission plans or missing property for code: {$code}", [
|
||||
'admissionPlans' => $admissionPlans
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$filteredPlans = $this->admissionPlanService->filterEmptyNaprOrProg($admissionPlans->competitons_groups);
|
||||
|
||||
if (empty($filteredPlans)) {
|
||||
Log::info("No valid plans after filtering for code: {$code}");
|
||||
continue;
|
||||
}
|
||||
|
||||
$items = $this->admissionPlanService->transformData($filteredPlans);
|
||||
|
||||
if (empty($items)) {
|
||||
Log::info("No items after transformation for code: {$code}");
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($items as $item) {
|
||||
// Проверка структуры $item
|
||||
if (!isset($item['id'], $item['plan']->competitions, $item['plan']->exams)) {
|
||||
Log::warning("Invalid item structure", ['item' => $item]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$eduPrograms = EducationalProgram::where('inner_code', $item['id'])->get();
|
||||
|
||||
if ($eduPrograms->isEmpty()) {
|
||||
Log::info("No educational programs found for inner_code: {$item['id']}");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$contestData = $this->admissionPlanService->convertToSaveContestData($item['plan']->competitions);
|
||||
$examData = $this->admissionPlanService->convertToSaveExamData($item['plan']->exams);
|
||||
|
||||
foreach ($eduPrograms as $eduProgram) {
|
||||
$eduProgram->admission_plans()->create([
|
||||
'admission_campaigns_id' => $this->getActiveCampaign()->id,
|
||||
'exams' => $examData,
|
||||
'contests' => $contestData,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error("Error processing admission plan for item: {$item['id']}", [
|
||||
'error' => $e->getMessage(),
|
||||
'item' => $item
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error in admission plans processing', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getActiveCampaign()
|
||||
{
|
||||
$activeCampaign = AdmissionCampaign::where('status', 1)->first();
|
||||
|
||||
if (!$activeCampaign) {
|
||||
throw new \Exception('No active admission campaign found');
|
||||
}
|
||||
|
||||
return $activeCampaign;
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,15 @@ class CreateEducationalProgram implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
private $educatinalProgramService;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
|
||||
private EducationalProgramService $educatinalProgramService;
|
||||
public function __construct()
|
||||
{
|
||||
$this->educatinalProgramService = new EducationalProgramService();
|
||||
$this->educatinalProgramService = app(EducationalProgramService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,7 +45,8 @@ class BreadcrumbService
|
||||
];
|
||||
}
|
||||
|
||||
private function generatePath(string $routeName): ?string
|
||||
|
||||
private function generatePath(?string $routeName): string|null
|
||||
{
|
||||
if ($routeName === 'page.view') {
|
||||
return request()->path();
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Vicon\DirectionStudy;
|
||||
|
||||
use App\Jobs\CreateDirectionStudy;
|
||||
use App\Jobs\CreateEducationalProgram;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AdmissionPlanService
|
||||
{
|
||||
public function getLevelEducationCodes(object $campaign) : array
|
||||
{
|
||||
return array_map(function ($item) {
|
||||
return (int)$item->campaign_levels_code;
|
||||
}, $campaign->groups);
|
||||
}
|
||||
|
||||
public function findActiveCampaign(array $campaigns): object|null
|
||||
{
|
||||
return array_reduce($campaigns, function($carry, $item) {
|
||||
return $carry ?? ($item->status == 1 ? $item : null);
|
||||
});
|
||||
}
|
||||
|
||||
public function getCampaigns(): array
|
||||
{
|
||||
try {
|
||||
$response = $this->callAPI(
|
||||
"https://db-nica.ru/api/v1/campaigns",
|
||||
env('VICON_TOKEN')
|
||||
);
|
||||
if (!is_array($response)) {
|
||||
Log::warning('Unexpected response type in getCampaigns', [
|
||||
'type' => gettype($response),
|
||||
'response' => $response
|
||||
]);
|
||||
}
|
||||
|
||||
return $response;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('API call failed in getCampaigns', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
return []; // или вернуть пустой объект (object)[]
|
||||
}
|
||||
}
|
||||
|
||||
public function getAdmissionPlans(int $campaign_levels_code): object|array
|
||||
{
|
||||
try {
|
||||
$response = $this->callAPI(
|
||||
"https://db-nica.ru/api/v1/planPriema/$campaign_levels_code",
|
||||
env('VICON_TOKEN')
|
||||
);
|
||||
|
||||
if (!is_object($response)) {
|
||||
Log::warning('Unexpected response type in getAdmissionPlans', [
|
||||
'expected' => 'object',
|
||||
'actual' => gettype($response),
|
||||
'campaign_levels_code' => $campaign_levels_code,
|
||||
'response' => $response
|
||||
]);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return $response;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('API call failed in getAdmissionPlans', [
|
||||
'error' => $e->getMessage(),
|
||||
'campaign_levels_code' => $campaign_levels_code,
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function filterEmptyNaprOrProg(array $array): array
|
||||
{
|
||||
return array_values(array_filter($array, function ($item) {
|
||||
return !empty($item->napr_or_prog);
|
||||
}));
|
||||
}
|
||||
|
||||
public function transformData(array $data) : array
|
||||
{
|
||||
return array_map(function ($item) {
|
||||
$array = [];
|
||||
$array['id'] = $item->napr_or_prog[0]->inner_code;
|
||||
$array['plan'] = $item->groups_condition[0];
|
||||
return $array;
|
||||
}, $data);
|
||||
}
|
||||
|
||||
|
||||
public function convertToSaveExamData(array $data) : array
|
||||
{
|
||||
return array_map(function ($item) {
|
||||
$array = [];
|
||||
$array['title'] = $item->exam_name;
|
||||
$array['priority'] = $item->priority;
|
||||
$array['types'] = array_map(function ($i) {
|
||||
return [
|
||||
'type' => $i->type,
|
||||
'min_ball' => $i->min_ball,
|
||||
];
|
||||
}, $item->types);
|
||||
return $array;
|
||||
}, $data);
|
||||
}
|
||||
|
||||
public function convertToSaveContestData(array $data) : array
|
||||
{
|
||||
return array_map(function ($item) {
|
||||
$array = [];
|
||||
$array['form_education'] = $item->form_obuch;
|
||||
$array['places'] = [
|
||||
'form_budget' => $item->source,
|
||||
'count' => $item->count_places
|
||||
];
|
||||
return $array;
|
||||
|
||||
}, $data);
|
||||
}
|
||||
|
||||
private function callAPI(string $endpoint, string $token = null): object|array
|
||||
{
|
||||
try {
|
||||
$response = Http::withToken($token)->get($endpoint);
|
||||
$data = $response->object();
|
||||
|
||||
if (isset($data->message)) {
|
||||
throw new \Exception($data->message);
|
||||
}
|
||||
|
||||
return $data;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Ошибка при вызове API: ' . $e->getMessage());
|
||||
throw $e; // Перебрасываем исключение
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ class EducationalProgramService
|
||||
$programs = array_merge($programs, $data->rows);
|
||||
}
|
||||
foreach ($programs as $program) {
|
||||
array_push($programsUuid, $program->uuid);
|
||||
$programsUuid[] = $program->uuid;
|
||||
}
|
||||
return $programsUuid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user