portal.mkgtu.ru/common/modules/abiturient/models/bachelor/AdmissionAgreement.php

473 lines
14 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace common\modules\abiturient\models\bachelor;
use backend\models\UploadableFileTrait;
use common\components\AfterValidateHandler\LoggingAfterValidateHandler;
use common\components\changeHistoryHandler\interfaces\ChangeHistoryHandlerInterface;
use common\components\CodeSettingsManager\CodeSettingsManager;
use common\components\FilesWorker\FilesWorker;
use common\components\ini\iniGet;
use common\models\errors\RecordNotValid;
use common\models\interfaces\ArchiveModelInterface;
use common\models\interfaces\FileToSendInterface;
use common\models\relation_presenters\comparison\interfaces\ICanGivePropsToCompare;
use common\models\relation_presenters\comparison\interfaces\IHaveIdentityProp;
use common\models\relation_presenters\OneToManyRelationPresenter;
use common\models\SendingFile;
use common\models\traits\ArchiveTrait;
use common\models\User;
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistory;
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistoryClasses;
use common\modules\abiturient\models\bachelor\changeHistory\interfaces\ChangeLoggedModelInterface;
use common\modules\abiturient\models\drafts\IHasRelations;
use common\modules\abiturient\models\interfaces\ICanGetPathToStoreFile;
use common\modules\abiturient\models\interfaces\IHaveCallbackAfterDraftCopy;
use Yii;
use yii\base\UserException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
class AdmissionAgreement extends ActiveRecord
implements
FileToSendInterface,
ChangeLoggedModelInterface,
ArchiveModelInterface,
IHasRelations,
IHaveIdentityProp,
ICanGetPathToStoreFile,
ICanGivePropsToCompare,
IHaveCallbackAfterDraftCopy
{
use ArchiveTrait;
use UploadableFileTrait;
const STATUS_NOTVERIFIED = 0;
const STATUS_VERIFIED = 1;
const STATUS_MARKED_TO_DELETE = 2;
public const SCENARIO_NEW_AGREEMENT = 'insert';
public const SCENARIO_RECOVER = 'recover';
public $file;
const DOCUMENT_TYPE_PREDEFINED_DATA_NAME = 'СогласиеНаЗачисление';
public static function tableName()
{
return '{{%admission_agreement}}';
}
public static function getFileRelationTable()
{
return '{{%agreements_files}}';
}
public static function getFileRelationColumn()
{
return 'agreement_id';
}
public function behaviors()
{
return [
TimestampBehavior::class,
];
}
public function rules()
{
return [
[['archived_at'], 'integer'],
[
[
'sent_at',
'speciality_id',
],
'integer'
],
[
['speciality_id'],
'required'
],
[
['speciality_id'],
'validateUniqueSpec',
'on' => self::SCENARIO_NEW_AGREEMENT
],
[
'status',
'default',
'value' => self::STATUS_NOTVERIFIED
],
[['archive'], 'boolean'],
[
'status',
'in',
'range' => [
AdmissionAgreement::STATUS_NOTVERIFIED,
AdmissionAgreement::STATUS_VERIFIED,
AdmissionAgreement::STATUS_MARKED_TO_DELETE,
]
],
[
['file'],
'file',
'extensions' => AdmissionAgreement::getExtensionsListForRules(),
'skipOnEmpty' => true,
'maxSize' => iniGet::getUploadMaxFilesize(false),
'except' => [static::SCENARIO_RECOVER]
],
];
}
public static function getExtensionsListForRules(): string
{
return implode(', ', static::getExtensionsList());
}
public static function getExtensionsList(): array
{
return FilesWorker::getAllowedExtensionsToUploadList();
}
public function validateUniqueSpec()
{
if ($this->status === self::STATUS_MARKED_TO_DELETE) {
return true;
}
if (AdmissionAgreement::find()
->active()
->andWhere([AdmissionAgreement::tableName() . '.speciality_id' => $this->speciality_id])
->andWhere(['not', [AdmissionAgreement::tableName() . '.status' => self::STATUS_MARKED_TO_DELETE]])
->exists()
) {
$this->addError(
'speciality_id',
Yii::t(
'abiturient/bachelor/application/admission-agreement',
'Подсказка с ошибкой для поля "speciality_id"; формы согласия: `Невозможно прикрепить несколько согласий на зачисление на одно направление подготовки.`'
)
);
return false;
}
return true;
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_NEW_AGREEMENT] = $scenarios[self::SCENARIO_DEFAULT];
return $scenarios;
}
public function getStatusString()
{
switch ($this->status) {
case self::STATUS_NOTVERIFIED:
return Yii::t('abiturient/bachelor/application/admission-agreement', 'Статус согласия: `Не подтверждено`');
case self::STATUS_VERIFIED:
return Yii::t('abiturient/bachelor/application/admission-agreement', 'Статус согласия: `Подтверждено`');
case self::STATUS_MARKED_TO_DELETE:
return Yii::t('abiturient/bachelor/application/admission-agreement', 'Статус согласия: `Отклонено`');
default:
return Yii::t('abiturient/bachelor/application/admission-agreement', 'Статус согласия: `Неизвестно`');
}
}
public function attributeLabels()
{
return [
'file' => Yii::t('abiturient/bachelor/application/admission-agreement', 'Подпись для поля "file"; формы согласия: `файл`'),
'status' => Yii::t('abiturient/bachelor/application/admission-agreement', 'Подпись для поля "status"; формы согласия: `Статус`'),
'statusString' => Yii::t('abiturient/bachelor/application/admission-agreement', 'Подпись для поля "status"; формы согласия: `Статус`'),
'filename' => Yii::t('abiturient/bachelor/application/admission-agreement', 'Подпись для поля "filename"; формы согласия: `Имя файла`'),
'speciality_id' => Yii::t('abiturient/bachelor/application/admission-agreement', 'Подпись для поля "speciality_id"; формы согласия: `Направление подготовки`'),
];
}
public function getSpeciality()
{
return $this->hasOne(BachelorSpeciality::class, ['id' => 'speciality_id']);
}
public function getUser()
{
return ArrayHelper::getValue($this, 'speciality.application.user');
}
public function getRawAgreementDecline()
{
return $this->hasOne(AgreementDecline::class, ['agreement_id' => 'id'])
->orderBy([AgreementDecline::tableName() . '.archive' => SORT_ASC]);
}
public function getAgreementDecline()
{
return $this->hasOne(AgreementDecline::class, ['agreement_id' => 'id'])
->active()
->orderBy([AgreementDecline::tableName() . '.archive' => SORT_ASC]);
}
protected function getOwnerId()
{
return $this->user->id;
}
public function checkAccess($user)
{
if ($user->isModer()) {
return true;
} elseif ($user->id == $this->getOwnerId()) {
return true;
} else {
return false;
}
}
public function makeDeclined()
{
if ($this->status === AdmissionAgreement::STATUS_NOTVERIFIED) {
return $this->archive();
}
$user_id = ArrayHelper::getValue($this, 'speciality.application.user.id');
$app_code = ArrayHelper::getValue($this, 'speciality.application_code');
$campaign_code = ArrayHelper::getValue($this, 'speciality.application.type.campaign.referenceType.reference_id');
$transaction = Yii::$app->db->beginTransaction();
try {
if (isset($user_id, $app_code, $campaign_code)) {
$toDeleteEntity = new AdmissionAgreementToDelete([
'user_id' => $user_id,
'agreement_id' => $this->id,
'application_code' => $app_code,
'campaign_code' => $campaign_code,
'archive' => false
]);
$result = $this->markToDelete() && $toDeleteEntity->validate();
if ($result) {
$toDeleteEntity->save(false);
$transaction->commit();
return true;
}
}
$transaction->rollBack();
return false;
} catch (\Throwable $e) {
$transaction->rollBack();
throw $e;
}
}
public function markToDelete()
{
$this->status = self::STATUS_MARKED_TO_DELETE;
if ($this->validate()) {
$this->save(false);
return true;
}
return false;
}
public function archiveAllDeclines()
{
if (isset($this->speciality->application_code)) {
AdmissionAgreementToDelete::updateAll(['archive' => true], [
'user_id' => $this->user->id,
'id' => $this->getRawAgreementToDelete()->select('id')->column()
]);
AgreementDecline::updateAll(['archive' => true], [
'id' => $this->getAgreementDecline()->select('id')->column()
]);
}
}
public function getRawAgreementToDelete()
{
return $this->hasOne(AdmissionAgreementToDelete::class, ['agreement_id' => 'id']);
}
public function getAgreementToDelete()
{
return $this->getRawAgreementToDelete()->andOnCondition([AdmissionAgreementToDelete::tableName() . '.archive' => false]);
}
public function getClassTypeForChangeHistory(): int
{
return ChangeHistoryClasses::CLASS_AGREEMENT;
}
public function getChangeLoggedAttributes()
{
return [];
}
public function getOldClass(): ChangeLoggedModelInterface
{
return $this;
}
public function getEntityIdentifier(): ?string
{
if ($this->speciality !== null) {
return $this->speciality->getEntityIdentifier();
}
return '';
}
public function getChangeHistoryHandler(): ?ChangeHistoryHandlerInterface
{
return null;
}
public function getEntityChangeType(): int
{
return ChangeHistory::CHANGE_HISTORY_NEW_AGREEMENT;
}
public function setChangeHistoryHandler(ChangeHistoryHandlerInterface $handler)
{
return null;
}
public function beforeArchive()
{
if ($this->agreementDecline) {
$this->agreementDecline->archive();
}
}
public function beforeDelete()
{
if (parent::beforeDelete()) {
$transaction = Yii::$app->db->beginTransaction();
$deleteSuccess = true;
try {
$errorFrom = '';
$agreementDecline = $this->getRawAgreementDecline()->all();
if (!empty($agreementDecline)) {
foreach ($agreementDecline as $dataToDelete) {
$deleteSuccess = $dataToDelete->delete();
if (!$deleteSuccess) {
$errorFrom .= "{$this->tableName()} -> {$dataToDelete->tableName()} -> {$dataToDelete->id}\n";
break;
}
}
}
if ($deleteSuccess) {
$agreementToDelete = $this->getRawAgreementToDelete()->all();
if (!empty($agreementToDelete)) {
foreach ($agreementToDelete as $dataToDelete) {
$deleteSuccess = $dataToDelete->delete();
if (!$deleteSuccess) {
$errorFrom .= "{$this->tableName()} -> {$dataToDelete->tableName()} -> {$dataToDelete->id}\n";
break;
}
}
}
}
if ($deleteSuccess) {
$this->deleteAttachedFile();
$transaction->commit();
} else {
Yii::error("Ошибка при удалении данных с портала. В таблице: {$errorFrom}");
$transaction->rollBack();
return false;
}
return true;
} catch (\Throwable $e) {
$transaction->rollBack();
Yii::error("Ошибка при удалении данных с портала. " . $e->getMessage());
return false;
}
} else {
return false;
}
}
public function afterValidate()
{
(new LoggingAfterValidateHandler())
->setModel($this)
->invoke();
}
public function getRelationsInfo(): array
{
return [
new OneToManyRelationPresenter('agreementDeclines', [
'parent_instance' => $this,
'child_class' => AgreementDecline::class,
'child_column_name' => 'agreement_id',
]),
new OneToManyRelationPresenter('agreementsToDelete', [
'parent_instance' => $this,
'child_class' => AdmissionAgreementToDelete::class,
'child_column_name' => 'agreement_id',
'ignore_in_comparison' => true,
]),
];
}
public function getIdentityString(): string
{
$declined = (int)(bool)$this->agreementDecline;
return "{$this->status}_{$declined}_{$this->filename}";
}
public function getPropsToCompare(): array
{
return [
'statusString',
'filename',
];
}
}