portal.mkgtu.ru/common/services/abiturientController/bachelor/entrant_test/EntrantTestService.php

401 lines
13 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace common\services\abiturientController\bachelor\entrant_test;
use common\components\ChangeHistoryManager;
use common\components\EntrantTestManager\EntrantTestManager;
use common\components\RegulationRelationManager;
use common\models\AttachmentType;
use common\models\dictionary\StoredReferenceType\StoredChildDisciplineReferenceType;
use common\models\dictionary\StoredReferenceType\StoredDisciplineReferenceType;
use common\models\errors\RecordNotValid;
use common\models\User;
use common\modules\abiturient\models\bachelor\BachelorApplication;
use common\modules\abiturient\models\bachelor\CgetChildSubject;
use common\modules\abiturient\models\bachelor\CgetEntranceTest;
use common\modules\abiturient\models\bachelor\CgetEntranceTestSet;
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistory;
use common\modules\abiturient\models\bachelor\EgeResult;
use common\services\abiturientController\bachelor\BachelorService;
use Throwable;
use Yii;
use yii\base\UserException;
use yii\helpers\ArrayHelper;
class EntrantTestService extends BachelorService
{
public function getRegulationsAndAttachmentsForEntrantTest(BachelorApplication $application): array
{
return $this->getRegulationsAndAttachments(
$application,
AttachmentType::RELATED_ENTITY_EGE,
RegulationRelationManager::RELATED_ENTITY_EGE
);
}
public function postProcessingRegulationsAndAttachments(
BachelorApplication $application,
array $attachments,
array $regulations
): array
{
$hasChanges = false;
if ($application->canEdit()) {
[
'hasError' => $hasError,
'hasChanges' => $hasChanges,
] = EntrantTestManager::proceedEntrantTestFromPost($this->request, $application);
if (!$hasError) {
[
'hasChanges' => $hasChangesTmp,
'attachments' => $attachments,
'regulations' => $regulations,
] = parent::postProcessingRegulationsAndAttachments($application, $attachments, $regulations);
$hasChanges |= $hasChangesTmp;
}
}
return [
'hasChanges' => $hasChanges,
'attachments' => $attachments,
'regulations' => $regulations,
];
}
public function getNextStep(BachelorApplication $application, string $currentStep = 'ege-result'): string
{
return parent::getNextStep($application, $currentStep);
}
public function checkAttachmentFiles(
BachelorApplication $application,
bool $canEdit,
?string $attachmentTypeRelatedEntity = null
): array
{
return parent::checkAttachmentFiles(
$application,
$canEdit,
AttachmentType::RELATED_ENTITY_EGE
);
}
public function defineDisciplineSet(BachelorApplication $application, User $currentUser): array
{
$hasError = false;
$hasChanges = false;
$classForAlert = '';
$messageForAlert = '';
if ($application->canEdit()) {
$db = EgeResult::getDb();
$transaction = $db->beginTransaction();
try {
[
'hasError' => $hasError,
'messageForAlert' => $messageForAlert
] = $this->writeHistoryChanges($application, $currentUser);
if (!$hasError) {
$classForAlert = 'alert alert-warning';
$messageForAlert = Yii::$app->configurationManager->getText('no_data_saved_text');
$hasChanges = EgeResult::loadFromPost($application, $this->request->post());
if ($hasChanges) {
$application->resetStatus();
$classForAlert = 'alert alert-success';
$messageForAlert = Yii::t(
'abiturient/bachelor/ege/all',
'Сообщение об успешном сохранении набора ВИ; на стр. ВИ: `Набор вступительных испытаний подтвержден.`'
);
$transaction->commit();
} else {
$transaction->rollBack();
}
} else {
$classForAlert = 'alert alert-danger';
$messageForAlert = Yii::t(
'abiturient/bachelor/ege/all',
'Сообщение о не удачном заполнении набора ВИ; на стр. ВИ: `Ошибка заполнения актуальных вступительных испытаний. Обратитесь к администратору.`'
);
throw new UserException($messageForAlert);
}
} catch (Throwable $e) {
$hasError = true;
$transaction->rollBack();
Yii::error(
'Критическая ошибка обработки наборов ВИ.' . PHP_EOL . print_r(['throwable' => $e->getMessage()], true),
'EntrantTestService.defineDisciplineSet'
);
throw $e;
}
}
return [
'hasError' => $hasError,
'classForAlert' => $classForAlert,
'messageForAlert' => $messageForAlert
];
}
public function solvedConflict(BachelorApplication $application): void
{
$deletedIds = [];
$egeResults = $application->egeResults;
[
'entranceTestsCollection' => $entranceTestsCollection,
'childrenEntranceTestsCollection' => $childrenEntranceTestsCollection
] = $this->getEntranceTestsCollections($application);
foreach ($egeResults as $result) {
if (in_array($result->id, $deletedIds)) {
continue;
}
if (!$this->mainDisciplineSolvedConflict($result, $entranceTestsCollection)) {
continue;
}
$this->childrenDisciplineSolvedConflict($result, $childrenEntranceTestsCollection);
}
}
private function mainDisciplineSolvedConflict(EgeResult $result, array $entranceTestsCollection): bool
{
$isArchived = ArrayHelper::getValue($result, 'cgetDiscipline.archive', true);
if (!$isArchived) {
return false;
}
$referenceUid = ArrayHelper::getValue($result, 'cgetDiscipline.reference_uid', '');
$newDisciplineId = ArrayHelper::getValue($entranceTestsCollection, $referenceUid);
if (!$newDisciplineId) {
$result->delete();
return false;
}
$result->cget_discipline_id = $newDisciplineId;
if (!$result->save()) {
throw new RecordNotValid($result);
}
return true;
}
private function childrenDisciplineSolvedConflict(EgeResult $result, array $childrenEntranceTestsCollection): bool
{
$isArchived = ArrayHelper::getValue($result, 'cgetChildDiscipline.archive', true);
$referenceUid = ArrayHelper::getValue($result, 'cgetChildDiscipline.reference_uid', '');
if (
!$isArchived ||
empty($referenceUid) ||
empty($childrenEntranceTestsCollection)
) {
return false;
}
$newChildDisciplineId = ArrayHelper::getValue($childrenEntranceTestsCollection, $referenceUid);
if (!$newChildDisciplineId) {
$result->delete();
return false;
}
$result->cget_child_discipline_id = $newChildDisciplineId;
if (!$result->save()) {
throw new RecordNotValid($result);
}
return true;
}
private function getEntranceTestsCollections(BachelorApplication $application): array
{
return [
'entranceTestsCollection' => ArrayHelper::map(
$this->getEntranceTestsCollection($application),
'reference_uid',
'id'
),
'childrenEntranceTestsCollection' => ArrayHelper::map(
$this->getChildrenEntranceTestsCollection($application),
'reference_uid',
'id'
),
];
}
private function getEntranceTestsCollection(BachelorApplication $application): array
{
$availableSets = $application->getAvailableCgetEntranceTestSetIds();
$cgetEntranceTestTableName = CgetEntranceTest::tableName();
$cgetEntranceTestSetTableName = CgetEntranceTestSet::tableName();
$storedDisciplineReferenceTypeTableName = StoredDisciplineReferenceType::tableName();
$disciplines = StoredDisciplineReferenceType::find()
->select([
"{$storedDisciplineReferenceTypeTableName}.id",
"{$storedDisciplineReferenceTypeTableName}.reference_uid"
])
->leftJoin($cgetEntranceTestTableName, "{$storedDisciplineReferenceTypeTableName}.id = {$cgetEntranceTestTableName}.subject_ref_id")
->leftJoin($cgetEntranceTestSetTableName, "{$cgetEntranceTestTableName}.cget_entrance_test_set_id = {$cgetEntranceTestSetTableName}.id")
->andWhere([
"{$cgetEntranceTestTableName}.archive" => false,
"{$cgetEntranceTestSetTableName}.archive" => false,
"{$storedDisciplineReferenceTypeTableName}.archive" => false,
])
->andWhere(['IN', "{$cgetEntranceTestSetTableName}.id", $availableSets])
->groupBy([
"{$storedDisciplineReferenceTypeTableName}.id",
"{$storedDisciplineReferenceTypeTableName}.reference_uid"
])
->all();
return $disciplines;
}
private function getChildrenEntranceTestsCollection(BachelorApplication $application): array
{
$availableSets = $application->getAvailableCgetEntranceTestSetIds();
$cgetChildSubjectTableName = CgetChildSubject::tableName();
$cgetEntranceTestTableName = CgetEntranceTest::tableName();
$cgetEntranceTestSetTableName = CgetEntranceTestSet::tableName();
$storedChildDisciplineReferenceTypeTableName = StoredChildDisciplineReferenceType::tableName();
$disciplines = StoredChildDisciplineReferenceType::find()
->select([
"{$storedChildDisciplineReferenceTypeTableName}.id",
"{$storedChildDisciplineReferenceTypeTableName}.reference_uid"
])
->leftJoin($cgetChildSubjectTableName, "{$storedChildDisciplineReferenceTypeTableName}.id = {$cgetChildSubjectTableName}.child_subject_ref_id")
->leftJoin($cgetEntranceTestTableName, "{$cgetChildSubjectTableName}.cget_entrance_test_id = {$cgetEntranceTestTableName}.id")
->leftJoin($cgetEntranceTestSetTableName, "{$cgetEntranceTestTableName}.cget_entrance_test_set_id = {$cgetEntranceTestSetTableName}.id")
->andWhere([
"{$cgetChildSubjectTableName}.archive" => false,
"{$cgetEntranceTestTableName}.archive" => false,
"{$cgetEntranceTestSetTableName}.archive" => false,
"{$storedChildDisciplineReferenceTypeTableName}.archive" => false,
])
->andWhere(['IN', "{$cgetEntranceTestSetTableName}.id", $availableSets])
->groupBy([
"{$storedChildDisciplineReferenceTypeTableName}.id",
"{$storedChildDisciplineReferenceTypeTableName}.reference_uid"
])
->all();
return $disciplines;
}
protected function writeHistoryChanges(BachelorApplication $application, User $currentUser): array
{
$hasError = false;
$messageForAlert = '';
$change = ChangeHistoryManager::persistChangeForEntity($currentUser, ChangeHistory::CHANGE_HISTORY_EXAM_SET);
$change->application_id = $application->id;
if (!$change->save()) {
$hasError = true;
$messageForAlert = Yii::t(
'abiturient/bachelor/ege/all',
'Сообщение о не удачном сохранении изменений; на стр. ВИ: `Ошибка записи истории изменений. Обратитесь к администратору.`'
);
Yii::error(
'Ошибка записи истории изменений.' . PHP_EOL . print_r(['errors' => $change->errors], true),
'EntrantTestService.writeHistoryChanges'
);
}
return [
'hasError' => $hasError,
'messageForAlert' => $messageForAlert
];
}
}