portal.mkgtu.ru/common/services/abiturientController/bachelor/accounting_benefits/AccountingBenefitsService.php

503 lines
15 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace common\services\abiturientController\bachelor\accounting_benefits;
use Closure;
use common\components\AttachmentManager;
use common\components\configurationManager;
use common\components\filesystem\FilterFilename;
use common\components\ReferenceTypeManager\ContractorManager;
use common\models\Attachment;
use common\models\dictionary\AvailableDocumentTypesForConcession;
use common\models\dictionary\DocumentType;
use common\models\dictionary\DocumentTypesForConcessionJunctionToFilters;
use common\models\dictionary\Privilege;
use common\models\dictionary\SpecialMark;
use common\models\dictionary\StoredReferenceType\StoredAdmissionCampaignReferenceType;
use common\models\dictionary\StoredReferenceType\StoredAvailableDocumentTypeFilterReferenceType;
use common\models\ModelFrom1CByOData;
use common\models\User;
use common\modules\abiturient\models\bachelor\BachelorApplication;
use common\modules\abiturient\models\bachelor\BachelorPreferences;
use common\modules\abiturient\models\bachelor\BachelorTargetReception;
use common\services\abiturientController\bachelor\BachelorService;
use Throwable;
use Yii;
use yii\base\UserException;
use yii\caching\CacheInterface;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
use yii\web\NotFoundHttpException;
use yii\web\Request;
use ZipArchive;
class AccountingBenefitsService extends BachelorService
{
protected CacheInterface $cache;
public function __construct(
Request $request,
CacheInterface $cache,
configurationManager $configurationManager
) {
$this->cache = $cache;
parent::__construct($request, $configurationManager);
}
public function postProcessingRegulationsAndAttachments(
BachelorApplication $application,
array $attachments,
array $regulations
): array {
if ($this->request->post('UserRegulation') !== null) {
return parent::postProcessingRegulationsAndAttachments($application, $attachments, $regulations);
}
return [
'hasChanges' => false,
'attachments' => $attachments,
'regulations' => $regulations,
];
}
public function getNextStep(BachelorApplication $application, string $currentStep = 'accounting-benefits'): string
{
return parent::getNextStep($application, $currentStep);
}
public function canGenerateFilesToDownloadAccountingBenefits(?int $id = null, string $accountingBenefitsClass): bool
{
AccountingBenefitsService::checkIsCorrectAccountingBenefitsClass($accountingBenefitsClass);
if (isset($id)) {
$model = $accountingBenefitsClass::findOne($id);
if (isset($model)) {
return $model->getAttachments()->exists();
}
}
return false;
}
protected function getDocTypesByBachelorPreferenceCodeAndBachelorApplication(BachelorApplication $application, ?ModelFrom1CByOData $preference)
{
$ValueArray = null;
if ($preference) {
if ($preference instanceof Privilege) {
$subject_type = DocumentTypesForConcessionJunctionToFilters::SUBJECT_TYPE_PRIVILEGES;
} else {
$subject_type = DocumentTypesForConcessionJunctionToFilters::SUBJECT_TYPE_SPECIAL_MARKS;
}
$id_subject = $preference->ref_key;
$tnFilterJunctions = DocumentTypesForConcessionJunctionToFilters::tableName();
$tnAvailableDocumentTypeFilterRef = StoredAvailableDocumentTypeFilterReferenceType::tableName();
$query = AvailableDocumentTypesForConcession::find()
->joinWith('admissionCampaignRef', false)
->joinWith('documentTypeRef', false)
->joinWith(['filterJunctions'])
->joinWith('availableDocumentTypeFilterRef')
->andWhere(["{$tnFilterJunctions}.subject_type" => $subject_type])
->andWhere(["{$tnAvailableDocumentTypeFilterRef}.reference_uid" => $id_subject])
->andWhere([StoredAdmissionCampaignReferenceType::tableName() . '.reference_uid' => $application->type->rawCampaign->referenceType->reference_uid])
->andWhere(['dictionary_available_document_types_for_concession.archive' => false])
->select(DocumentType::tableName() . '.ref_key');
$ValueArray = DocumentType::find()
->notMarkedToDelete()
->active()
->select(['maxid' => 'max(dictionary_document_type.id)', 'dictionary_document_type.ref_key', 'dictionary_document_type.description'])
->andWhere(['dictionary_document_type.ref_key' => $query])
->andWhere(['dictionary_document_type.is_folder' => false])
->groupBy(['dictionary_document_type.ref_key', 'dictionary_document_type.description'])
->orderBy('dictionary_document_type.description')
->asArray()
->all();
}
if (empty($ValueArray)) {
$ValueArray = DocumentType::find()
->notMarkedToDelete()
->active()
->select(['maxid' => 'max(dictionary_document_type.id)', 'dictionary_document_type.ref_key', 'dictionary_document_type.description'])
->andWhere(['dictionary_document_type.is_folder' => false])
->groupBy(['dictionary_document_type.ref_key', 'dictionary_document_type.description'])
->orderBy('dictionary_document_type.description')
->asArray()
->all();
}
return $ValueArray;
}
protected function initBachelorPreferences(BachelorApplication $application, string $type): BachelorPreferences
{
$model = new BachelorPreferences();
$model->id_application = $application->id;
$model->setPreferenceType($type);
return $model;
}
protected function getDocumentItems(?string $docTypeUid = null): array
{
$tnDocumentType = DocumentType::tableName();
$docsQuery = DocumentType::find()
->notMarkedToDelete()
->active()
->andWhere(['is_folder' => false])
->orderBy("{$tnDocumentType}.description");
if ($docTypeUid) {
$docsQuery->andWhere(["{$tnDocumentType}.ref_key" => $docTypeUid]);
}
return ArrayHelper::map($docsQuery->all(), 'id', 'description');
}
protected function editAccountingBenefits(string $formName)
{
if ($this->request->isPost) {
$appId = $this->request->post($formName)['id_application'];
$id = $this->request->post($formName)['id'];
if ($appId) {
$application = $this->getApplication($appId);
return [
'id' => $id,
'appId' => $appId,
'application' => $application,
];
}
}
throw new UserException('Не переданы необходимые параметры');
}
protected function getAccountingBenefitsQueryForEditFunction(
int $id,
int $appId,
string $accountingBenefitsClass
): ActiveQuery {
AccountingBenefitsService::checkIsCorrectAccountingBenefitsClass($accountingBenefitsClass);
$tnAccountingBenefits = $accountingBenefitsClass::tableName();
return $accountingBenefitsClass::find()
->andWhere([
"{$tnAccountingBenefits}.id" => $id,
"{$tnAccountingBenefits}.id_application" => $appId,
]);
}
protected function saveNewAccountingBenefits(
?int $id,
string $formName
): BachelorApplication {
if ($this->request->isPost) {
if (!$id) {
$id = $this->request->post($formName)['id_application'];
}
return $this->getApplication($id);
}
throw new UserException('Не переданы необходимые параметры');
}
protected function generateFilesToDownloadAccountingBenefits(
User $currentUser,
?int $id,
string $accountingBenefitClass,
Closure $fileNameCallback,
string $throwMessage
): array {
AccountingBenefitsService::checkIsCorrectAccountingBenefitsClass($accountingBenefitClass);
$accountingBenefit = $accountingBenefitClass::findOne((int)$id);
if ($accountingBenefit != null) {
$zip = new ZipArchive();
$collection = $accountingBenefit->attachmentCollection;
$filename = FilterFilename::sanitize($fileNameCallback($accountingBenefit, $collection));
if ($zip->open(Yii::getAlias("@storage/web/tempZip/{$filename}"), ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new UserException('Не удалось создать архив.');
}
foreach ($collection->attachments as $key => $attachment) {
if ($attachment->checkAccess($currentUser)) {
$path = $attachment->getAbsPath();
if ($path && file_exists($path)) {
$number = $key + 1;
$zip->addFile(
$path,
FilterFilename::sanitize("{$number}. " .
$attachment->getAttachmentTypeName() .
'.' .
$attachment->extension)
);
}
}
}
if ($zip->numFiles > 0) {
$pathToZipArchive = $zip->filename;
$zip->close();
return [
'filename' => $filename,
'pathToZipArchive' => $pathToZipArchive
];
} else {
throw new UserException('Нет файлов для отправки.');
}
}
throw new NotFoundHttpException($throwMessage);
}
protected function updateAccountingBenefitsFromPost(
User $currentUser,
BachelorApplication $application,
$accountingBenefitsFrom,
Closure $beforeSaveCallback,
string $errorMessageTemplate
): array {
$saveSuccess = false;
$hasChangedAttributes = false;
if ($accountingBenefitsFrom->load($this->request->post())) {
$this->updateContractorFromPost($accountingBenefitsFrom);
$accountingBenefitsFrom = $beforeSaveCallback($accountingBenefitsFrom);
$hasChangedAttributes = $accountingBenefitsFrom->hasChangedAttributes();
if ($accountingBenefitsFrom->save()) {
if (!$currentUser->isModer()) {
$application->resetStatus();
}
$attachedFileHashList = $accountingBenefitsFrom->buildAttachmentHash();
AttachmentManager::handleAttachmentUpload([$accountingBenefitsFrom->attachmentCollection]);
$saveSuccess = true;
if (!$accountingBenefitsFrom->checkIfDocumentIsChanged($attachedFileHashList)) {
$accountingBenefitsFrom->setDocumentCheckStatusNotVerified();
$accountingBenefitsFrom->save(['document_check_status_ref_id']);
$hasChangedAttributes = true;
}
} else {
$log = ['data' => [
'id' => $accountingBenefitsFrom->id,
'id_application' => $application->id,
'formName' => $accountingBenefitsFrom->formName(),
]];
Yii::error(
$errorMessageTemplate .
PHP_EOL .
print_r($accountingBenefitsFrom->errors, true) .
PHP_EOL .
print_r($log, true),
'AccountingBenefitsService.updateAccountingBenefitsFromPost'
);
}
}
return [$accountingBenefitsFrom, $saveSuccess, $hasChangedAttributes];
}
protected function archiveAccountingBenefit(
?int $id = null,
User $currentUser,
string $accountingBenefitsClass,
string $errorMessageOnFileDeletion,
string $errorMessageOnAccountingBenefitArchiving,
bool $updateApplicationHistory = true
): void {
if (isset($id)) {
AccountingBenefitsService::checkIsCorrectAccountingBenefitsClass($accountingBenefitsClass);
$tnAccountingBenefits = $accountingBenefitsClass::tableName();
$model = $accountingBenefitsClass::find()
->notInEnlistedApp()
->andWhere(["{$tnAccountingBenefits}.id" => $id])
->one();
if (isset($model) && !$model->read_only) {
$db = $accountingBenefitsClass::getDb();
$transaction = $db->beginTransaction();
if (!isset($transaction)) {
throw new UserException('Невозможно начать транзакцию');
}
try {
foreach ($model->attachments as $attachment) {
if (!$attachment->safeDelete($currentUser, $updateApplicationHistory)) {
throw new UserException($errorMessageOnFileDeletion);
}
}
if (!$model->archive()) {
throw new UserException($errorMessageOnAccountingBenefitArchiving);
}
if (!$currentUser->isModer()) {
$model->application->resetStatus();
}
$transaction->commit();
} catch (Throwable $e) {
$transaction->rollBack();
throw $e;
}
}
}
}
private static function checkIsCorrectAccountingBenefitsClass(string $accountingBenefitsClass): bool
{
$correctAccountingBenefitsClasses = [
BachelorPreferences::class,
BachelorTargetReception::class,
];
if (in_array(
$accountingBenefitsClass,
$correctAccountingBenefitsClasses
)) {
return true;
}
throw new UserException("Был передан класс не относящийся к категории «особых прав» ({$accountingBenefitsClass})");
}
protected function updateContractorFromPost($accountingBenefitsFrom): void
{
if ($accountingBenefitsFrom->notFoundContractor) {
$accountingBenefitsFrom->contractor_id = ContractorManager::Upsert(
$this->request->post('Contractor'),
$accountingBenefitsFrom->documentType
)->id;
}
}
}