portal.mkgtu.ru/common/services/abiturientController/bachelor/AdmissionAgreementService.php

390 lines
14 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace common\services\abiturientController\bachelor;
use common\commands\command\AddToTimelineCommand;
use common\components\ChangeHistoryManager;
use common\components\configurationManager;
use common\components\exceptions\AdmissionAgreementException;
use common\models\errors\RecordNotValid;
use common\models\User;
use common\modules\abiturient\models\bachelor\AdmissionAgreement;
use common\modules\abiturient\models\bachelor\AgreementDecline;
use common\modules\abiturient\models\bachelor\ApplicationHistory;
use common\modules\abiturient\models\bachelor\BachelorApplication;
use common\modules\abiturient\models\bachelor\BachelorSpeciality;
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistory;
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistoryEntityClass;
use common\modules\abiturient\models\File;
use common\modules\abiturient\models\repositories\BachelorSpecialityRepository;
use common\services\abiturientController\bachelor\BachelorService;
use Yii;
use yii\helpers\ArrayHelper;
use yii\web\Request;
use yii\web\UploadedFile;
class AdmissionAgreementService extends BachelorService
{
protected $commandBus;
public function __construct(
Request $request,
configurationManager $configurationManager
) {
$this->request = $request;
$this->configurationManager = $configurationManager;
$this->commandBus = Yii::$app->commandBus;
}
public function checkAgreementAccessibility(BachelorApplication $application, BachelorSpeciality $speciality): array
{
if (
$application->haveAttachedAgreementExcludeNonBudget() &&
!$speciality->isCommercialBasis()
) {
return [
'canEdited' => false,
'consentAddErrors' => Yii::t(
'abiturient/bachelor/admission-agreement/all',
'Текст ошибки дублировании согласия на зачисление, на странице НП: `Невозможно прикрепить согласие, так как в системе уже есть информация о прикрепленном согласии на зачисление.`'
),
];
}
if (!$speciality->canAddAgreements()) {
return [
'canEdited' => false,
'consentAddErrors' => Yii::t(
'abiturient/bachelor/admission-agreement/all',
'Текст ошибки о блокировке согласия на зачисление, на странице НП: `Невозможно прикрепить согласие, так как запрещено редактировать согласие на зачисление.`'
),
];
}
if (!$speciality->checkAgreementConditions()) {
return [
'canEdited' => false,
'consentAddErrors' => Yii::t(
'abiturient/bachelor/admission-agreement/all',
'Текст ошибки о блокировке согласия на зачисление, на странице НП: `Невозможно прикрепить согласие на зачисление для данного основания поступления, обратитесь в приёмную кампанию.`'
),
];
}
return [
'canEdited' => true,
'consentAddErrors' => '',
];
}
protected function uploadAgreement(int $specialityId): ?AdmissionAgreement
{
$admissionAgreement = new AdmissionAgreement();
$admissionAgreement->load($this->request->post());
$admissionAgreement->speciality_id = $specialityId;
$admissionAgreement->setScenario(AdmissionAgreement::SCENARIO_NEW_AGREEMENT);
$admissionAgreement->file = UploadedFile::getInstance($admissionAgreement, 'file');
if (!$admissionAgreement->upload()) {
return null;
}
return $admissionAgreement;
}
protected function copyAgreement(AdmissionAgreement $agreement, BachelorSpeciality $toSpeciality): ?AdmissionAgreement
{
$admissionAgreement = new AdmissionAgreement();
$admissionAgreement->speciality_id = $toSpeciality->id;
$admissionAgreement->setScenario(AdmissionAgreement::SCENARIO_NEW_AGREEMENT);
if (!$admissionAgreement->save()) {
throw new RecordNotValid($admissionAgreement);
}
$admissionAgreement->link('linkedFile', $agreement->linkedFile);
return $admissionAgreement;
}
public function createAgreements(User $user, BachelorApplication $application, BachelorSpeciality $speciality): void
{
$addedAgreements = [];
$transaction = Yii::$app->db->beginTransaction();
try {
if (!$admissionAgreement = $this->uploadAgreement($speciality->id)) {
throw new AdmissionAgreementException("Не удалось создать согласие");
}
$addedAgreements[] = $admissionAgreement;
if (ArrayHelper::getValue($application, 'type.campaign.use_common_agreements', false) && $speciality->isInAgreementConditions()) {
foreach ($this->getSpecialitiesByAgreementConditions($application, $speciality) as $other_spec) {
if (!$other_spec->agreement) {
$addedAgreements[] = $this->copyAgreement($admissionAgreement, $other_spec);
}
}
}
foreach ($addedAgreements as $addedAgreement) {
$addToTimelineCommandConfig = $this->changeAgreementHistoryProcess(
$user,
$application,
$speciality,
$addedAgreement
);
$this->commandBus->handle(new AddToTimelineCommand($addToTimelineCommandConfig));
}
$transaction->commit();
} catch (\Throwable $e) {
$transaction->rollBack();
throw $e;
}
}
public function copyAgreementToAddedSpecialities(BachelorApplication $application, array $added_specialities): void
{
if (!ArrayHelper::getValue($application, 'type.campaign.use_common_agreements', false)) {
return;
}
$conditions = $application->type->campaign->agreementConditions ?? [];
$edu_source_ref_uids = ArrayHelper::getColumn($conditions, 'educationSourceRef.reference_uid');
$existing_spec = $application->getSpecialities()
->innerJoinWith('agreement', true)
->joinWith('speciality.educationSourceRef edu_source_ref', false)
->andWhere(['edu_source_ref.reference_uid' => $edu_source_ref_uids])
->one();
if (!$existing_spec) {
return;
}
foreach ($added_specialities as $added_speciality) {
if ($added_speciality->isInAgreementConditions()) {
$this->copyAgreement($existing_spec->agreement, $added_speciality);
}
}
}
protected function getSpecialitiesByAgreementConditions(BachelorApplication $application, BachelorSpeciality $speciality): array
{
$conditions = $application->type->campaign->agreementConditions ?? [];
$edu_source_ref_uids = ArrayHelper::getColumn($conditions, 'educationSourceRef.reference_uid');
return BachelorSpecialityRepository::GetSpecialitiesByAgreementConditons($speciality, $edu_source_ref_uids)->all();
}
protected function createAgreementDecline(AdmissionAgreement $agreement, File $file): AgreementDecline
{
$agreementDecline = new AgreementDecline();
$agreementDecline->agreement_id = $agreement->id;
$agreementDecline->archive = false;
$agreementDecline->file = $file;
if (!$agreementDecline->upload()) {
Yii::error(
'Ошибки валидации при отзыве согласия согласия' .
($agreement->hasErrors() ? "\nAgreement\n" .
print_r($agreement->errors, true) : '') .
($agreementDecline->hasErrors() ? "\nAgreementDecline\n" .
print_r($agreementDecline->errors, true) : ''),
'AdmissionAgreementService.uploadAgreementDecline'
);
throw new RecordNotValid($agreementDecline);
}
return $agreementDecline;
}
public function declineAgreements(User $user, BachelorApplication $application, AdmissionAgreement $agreement)
{
$agreementsToDecline = [$agreement];
if (ArrayHelper::getValue($application, 'type.campaign.use_common_agreements', false)) {
$agreements = AdmissionAgreement::find()
->innerJoinWith('speciality bachelor_spec', true)
->andWhere([AdmissionAgreement::tableName() . '.archive' => false])
->andWhere(['!=', AdmissionAgreement::tableName() . '.status', AdmissionAgreement::STATUS_MARKED_TO_DELETE])
->andWhere(['!=', AdmissionAgreement::tableName() . '.id', $agreement->id])
->andWhere(['bachelor_spec.application_id' => $application->id])
->all();
foreach ($agreements as $activeAgreement) {
if ($activeAgreement->speciality->isInAgreementConditions()) {
$agreementsToDecline[] = $activeAgreement;
}
}
}
$file = null;
$transaction = Yii::$app->db->beginTransaction();
try {
foreach ($agreementsToDecline as $agreementToDecline) {
if ($agreementToDecline->status === AdmissionAgreement::STATUS_NOTVERIFIED) {
$addToTimelineCommandConfig = $this->changeAgreementDeclineHistoryProcess(
$user,
$application,
$agreementToDecline->speciality,
$agreementToDecline
);
$this->commandBus->handle(new AddToTimelineCommand($addToTimelineCommandConfig));
} elseif ($agreementToDecline->status = AdmissionAgreement::STATUS_VERIFIED) {
if (!$file) {
$tmpDecline = new AgreementDecline();
$tmpDecline->agreement_id = $agreement->id;
$uploaded_file = UploadedFile::getInstance($tmpDecline, 'file');
$file = File::GetOrCreateByTempFile(
$tmpDecline->getPathToStoreFiles(),
$uploaded_file
);
}
$this->createAgreementDecline($agreementToDecline, $file);
if (!$agreementToDecline->makeDeclined()) {
throw new AdmissionAgreementException("Не удалось отозвать согласие");
}
$addToTimelineCommandConfig = $this->changeAgreementDeclineHistoryProcess(
$user,
$application,
$agreementToDecline->speciality,
$agreementToDecline,
);
$this->commandBus->handle(new AddToTimelineCommand($addToTimelineCommandConfig));
}
}
$transaction->commit();
} catch (\Throwable $e) {
$transaction->rollBack();
\Yii::error($e->getMessage(), 'declineAgreements');
throw $e;
}
}
public function changeAgreementHistoryProcess(
User $user,
BachelorApplication $application,
BachelorSpeciality $speciality,
AdmissionAgreement $admissionAgreement
): array {
$application->addApplicationHistory(ApplicationHistory::TYPE_AGREEMENT_CHANGED);
return $this->changeHistoryProcess(
$user,
$application,
$speciality,
$admissionAgreement,
'application_add_consent',
ChangeHistory::CHANGE_HISTORY_NEW_AGREEMENT
);
}
public function changeAgreementDeclineHistoryProcess(
User $user,
BachelorApplication $application,
BachelorSpeciality $speciality,
AdmissionAgreement $admissionAgreement
): array {
$admissionAgreement->archive();
return $this->changeHistoryProcess(
$user,
$application,
$speciality,
$admissionAgreement,
'application_return_consent',
ChangeHistory::CHANGE_HISTORY_AGREEMENT_DECLINE
);
}
private function changeHistoryProcess(
User $user,
BachelorApplication $application,
BachelorSpeciality $speciality,
AdmissionAgreement $admissionAgreement,
string $event,
int $changeHistoryType
): array {
$application->resetStatus();
$change = ChangeHistoryManager::persistChangeForEntity($user, $changeHistoryType);
$change->application_id = $application->id;
if (!$change->save()) {
throw new RecordNotValid($change);
}
$class = ChangeHistoryManager::persistChangeHistoryEntity($admissionAgreement, ChangeHistoryEntityClass::CHANGE_TYPE_INSERT);
$class->setChangeHistory($change);
if (!$class->save()) {
throw new RecordNotValid($class);
}
return [
'category' => 'abiturient',
'event' => $event,
'data' => [
'public_identity' => $user->getPublicIdentity(),
'user_id' => $user->getId(),
'campaign' => $application->type->campaignName,
'speciality' => $speciality->speciality->directionRef->reference_name ?? '',
]
];
}
}