669 lines
21 KiB
PHP
Executable File
669 lines
21 KiB
PHP
Executable File
<?php
|
|
|
|
namespace common\modules\abiturient\models;
|
|
|
|
use common\components\AfterValidateHandler\LoggingAfterValidateHandler;
|
|
use common\components\AttachmentManager;
|
|
use common\components\CodeSettingsManager\CodeSettingsManager;
|
|
use common\components\ReferenceTypeManager\ContractorManager;
|
|
use common\components\ReferenceTypeManager\exceptions\ReferenceManagerCannotSerializeDataException;
|
|
use common\components\ReferenceTypeManager\exceptions\ReferenceManagerValidationException;
|
|
use common\components\ReferenceTypeManager\exceptions\ReferenceManagerWrongReferenceTypeClassException;
|
|
use common\components\ReferenceTypeManager\ReferenceTypeManager;
|
|
use common\components\validation_rules_providers\RulesProviderByDocumentType;
|
|
use common\models\Attachment;
|
|
use common\models\attachment\attachmentCollection\AttachedEntityAttachmentCollection;
|
|
use common\models\AttachmentType;
|
|
use common\models\dictionary\Contractor;
|
|
use common\models\dictionary\DocumentType;
|
|
use common\models\dictionary\StoredReferenceType\StoredDocumentCheckStatusReferenceType;
|
|
use common\models\errors\RecordNotValid;
|
|
use common\models\interfaces\ArchiveModelInterface;
|
|
use common\models\interfaces\AttachmentLinkableEntity;
|
|
use common\models\interfaces\dynamic_validation_rules\IHavePropsRelatedToDocumentType;
|
|
use common\models\interfaces\IHaveDocumentCheckStatus;
|
|
use common\models\relation_presenters\AttachmentsRelationPresenter;
|
|
use common\models\relation_presenters\comparison\interfaces\ICanGivePropsToCompare;
|
|
use common\models\relation_presenters\comparison\interfaces\IHaveIdentityProp;
|
|
use common\models\traits\ArchiveTrait;
|
|
use common\models\traits\DocumentCheckStatusTrait;
|
|
use common\models\traits\FileAttachTrait;
|
|
use common\models\traits\HasDirtyAttributesTrait;
|
|
use common\models\traits\HtmlPropsEncoder;
|
|
use common\models\User;
|
|
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistoryClasses;
|
|
use common\modules\abiturient\models\bachelor\changeHistory\ChangeHistoryDecoratedModel;
|
|
use common\modules\abiturient\models\bachelor\changeHistory\interfaces\ChangeLoggedModelInterface;
|
|
use common\modules\abiturient\models\drafts\DraftsManager;
|
|
use common\modules\abiturient\models\drafts\IHasRelations;
|
|
use common\modules\abiturient\models\interfaces\ICanAttachFile;
|
|
use common\modules\abiturient\models\interfaces\ICanBeStringified;
|
|
use common\modules\abiturient\models\interfaces\QuestionaryConnectedInterface;
|
|
use common\modules\abiturient\models\parentData\ParentData;
|
|
use common\modules\abiturient\validators\PassportData\PassportDataValidation;
|
|
use stdClass;
|
|
use Yii;
|
|
use yii\behaviors\TimestampBehavior;
|
|
use yii\db\ActiveQuery;
|
|
use yii\db\ActiveRecord;
|
|
use yii\db\TableSchema;
|
|
use yii\helpers\ArrayHelper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PassportData extends ChangeHistoryDecoratedModel
|
|
implements
|
|
QuestionaryConnectedInterface,
|
|
ChangeLoggedModelInterface,
|
|
ArchiveModelInterface,
|
|
IHaveIdentityProp,
|
|
ICanGivePropsToCompare,
|
|
AttachmentLinkableEntity,
|
|
ICanAttachFile,
|
|
IHasRelations,
|
|
IHavePropsRelatedToDocumentType,
|
|
IHaveDocumentCheckStatus,
|
|
ICanBeStringified
|
|
{
|
|
use ArchiveTrait;
|
|
use FileAttachTrait;
|
|
use HtmlPropsEncoder;
|
|
use HasDirtyAttributesTrait;
|
|
use DocumentCheckStatusTrait;
|
|
|
|
const SCENARIO_GET_ANKETA = 'get_anketa';
|
|
const SCENARIO_SIGN_UP = 'sign_up';
|
|
const SCENARIO_CONTRACTOR_MAY_NOT_BE_FOUND = 'contractor_may_not_be_found';
|
|
public const SCENARIO_NOT_REQUIRED = 'not_required';
|
|
|
|
protected bool $_new_record = true;
|
|
|
|
|
|
public $notFoundContractor;
|
|
|
|
protected ?RulesProviderByDocumentType $_document_type_validation_extender = null;
|
|
|
|
public function __construct($config = [])
|
|
{
|
|
parent::__construct($config);
|
|
$this->_document_type_validation_extender = new RulesProviderByDocumentType($this);
|
|
}
|
|
|
|
public static function tableName()
|
|
{
|
|
return '{{%passport_data}}';
|
|
}
|
|
|
|
public function behaviors()
|
|
{
|
|
return [TimestampBehavior::class];
|
|
}
|
|
|
|
public function afterFind()
|
|
{
|
|
parent::afterFind();
|
|
$this->_new_record = false;
|
|
}
|
|
|
|
public function ownRequiredRules(): array
|
|
{
|
|
$passport_rf_required = ['series', 'contractor_id'];
|
|
return [
|
|
[
|
|
$passport_rf_required,
|
|
'required',
|
|
'when' => function ($model, $attribute) {
|
|
if (empty($model->documentType)) {
|
|
return false;
|
|
}
|
|
return ($model->documentType->ref_key == Yii::$app->configurationManager->getCode('russian_passport_guid'));
|
|
},
|
|
'whenClient' => "
|
|
function (attribute, value) {
|
|
$(attribute.input).parent('.form-group').removeClass('required');
|
|
$(attribute.input).parent('.form-group').find('label').removeClass('has-star');
|
|
|
|
var input = $('#{$this->clientFormName}-document_type_id');
|
|
if (input.length === 0) {
|
|
input = $('#{$this->clientFormName}-document_type_id_" . ($this->id ?? '0') . "');
|
|
}
|
|
if (
|
|
input.val() != '' &&
|
|
input.val() != " . CodeSettingsManager::GetEntityByCode('russian_passport_guid')->id . "
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
var result = true;
|
|
if (attribute === 'contractor_id') {
|
|
result = $('#{$this->clientFormName}-contractor_not_found-" . ($this->id ?? '0') . "').not(':checked');
|
|
}
|
|
if (result) {
|
|
$(attribute.input).parent('.form-group').addClass('required');
|
|
$(attribute.input).parent('.form-group').find('label').addClass('has-star');
|
|
}
|
|
|
|
return result;
|
|
}
|
|
",
|
|
'except' => [
|
|
self::SCENARIO_NOT_REQUIRED
|
|
]
|
|
],
|
|
];
|
|
}
|
|
|
|
public static function baseRules()
|
|
{
|
|
return [
|
|
[
|
|
[
|
|
'series',
|
|
'number'
|
|
],
|
|
'trim'
|
|
],
|
|
[
|
|
[
|
|
'archive',
|
|
'notFoundContractor',
|
|
'read_only',
|
|
],
|
|
'boolean'
|
|
],
|
|
[
|
|
[
|
|
'archive',
|
|
'notFoundContractor',
|
|
'read_only',
|
|
],
|
|
'default',
|
|
'value' => false
|
|
],
|
|
[
|
|
[
|
|
'questionary_id',
|
|
'document_type_id',
|
|
'contractor_id'
|
|
],
|
|
'integer'
|
|
],
|
|
[
|
|
['issued_date'],
|
|
'string',
|
|
'max' => 100
|
|
],
|
|
[
|
|
[
|
|
'series',
|
|
'number'
|
|
],
|
|
'string',
|
|
'max' => 50
|
|
],
|
|
[
|
|
'document_type_id',
|
|
'required',
|
|
'except' => [
|
|
self::SCENARIO_NOT_REQUIRED
|
|
]
|
|
],
|
|
[
|
|
['questionary_id'],
|
|
'required',
|
|
'except' => [
|
|
self::SCENARIO_GET_ANKETA,
|
|
self::SCENARIO_SIGN_UP,
|
|
self::SCENARIO_CONTRACTOR_MAY_NOT_BE_FOUND,
|
|
self::SCENARIO_NOT_REQUIRED
|
|
]
|
|
],
|
|
[
|
|
'country_id',
|
|
'safe'
|
|
],
|
|
[
|
|
[
|
|
'series',
|
|
'number',
|
|
],
|
|
PassportDataValidation::class,
|
|
'except' => [self::SCENARIO_GET_ANKETA],
|
|
],
|
|
[
|
|
['document_check_status_ref_id'],
|
|
'exist',
|
|
'skipOnError' => true,
|
|
'targetClass' => StoredDocumentCheckStatusReferenceType::class,
|
|
'targetAttribute' => ['document_check_status_ref_id' => 'id'],
|
|
],
|
|
];
|
|
}
|
|
|
|
|
|
|
|
|
|
public function rules()
|
|
{
|
|
return [...$this->_document_type_validation_extender->getRules(), ...static::baseRules()];
|
|
}
|
|
|
|
public function scenarios()
|
|
{
|
|
$scenarios = parent::scenarios();
|
|
$scenarios[self::SCENARIO_GET_ANKETA] = ['questionary_id', 'document_type_id', 'contractor_id', 'issued_date', 'series', 'number', 'archive'];
|
|
$scenarios[self::SCENARIO_SIGN_UP] = ['questionary_id', 'document_type_id', 'contractor_id', 'issued_date', 'series', 'number', 'archive', 'notFoundContractor'];
|
|
$scenarios[self::SCENARIO_NOT_REQUIRED] = $scenarios[self::SCENARIO_DEFAULT];
|
|
$scenarios[self::SCENARIO_CONTRACTOR_MAY_NOT_BE_FOUND] = $scenarios[self::SCENARIO_SIGN_UP];
|
|
return $scenarios;
|
|
}
|
|
|
|
|
|
|
|
|
|
public function attributeLabels()
|
|
{
|
|
return [
|
|
'number' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "number" формы "Паспортные данные": `Номер`'),
|
|
'series' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "series" формы "Паспортные данные": `Серия`'),
|
|
'issuedBy' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "issuedBy" формы "Паспортные данные": `Кем выдан`'),
|
|
'country_id' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "country_id" формы "Паспортные данные": `Гражданство`'),
|
|
'issued_date' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "issued_date" формы "Паспортные данные": `Когда выдан`'),
|
|
'questionary_id' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "questionary_id" формы "Паспортные данные": `Анкета`'),
|
|
'departmentCode' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "departmentCode" формы "Паспортные данные": `Код подразделения`'),
|
|
'document_type_id' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "document_type_id" формы "Паспортные данные": `Тип документа`'),
|
|
'documentTypeDescription' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "documentTypeDescription" формы "Паспортные данные": `Тип документа`'),
|
|
'contractor_id' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "contractor_id" формы "Паспортные данные": `Кем выдан`'),
|
|
'documentCheckStatus' => Yii::t('abiturient/questionary/passport-data', 'Подпись для поля "documentCheckStatus" формы "Паспортные данные": `Статус проверки документа`'),
|
|
];
|
|
}
|
|
|
|
public function getAbiturientQuestionary()
|
|
{
|
|
return $this->hasOne(AbiturientQuestionary::class, ['id' => 'questionary_id']);
|
|
}
|
|
|
|
public function getDocumentType()
|
|
{
|
|
return $this->hasOne(DocumentType::class, ['id' => 'document_type_id']);
|
|
}
|
|
|
|
public function getFormatted_issued_date()
|
|
{
|
|
return date('Y-m-d', strtotime($this->issued_date));
|
|
}
|
|
|
|
public function __set($name, $value)
|
|
{
|
|
$value = $this->encodeProp($name, $value);
|
|
|
|
if ($name == 'issued_date') {
|
|
$value = (string)date('d.m.Y', strtotime($value));
|
|
}
|
|
parent::__set($name, $value);
|
|
}
|
|
|
|
public function getChangeLoggedAttributes()
|
|
{
|
|
return [
|
|
'document_type_id' => function ($model) {
|
|
return ArrayHelper::getValue($model, 'documentTypeDescription');
|
|
},
|
|
'issued_date' => function ($model) {
|
|
return $model->issued_date == '01.01.1970' ? null : $model->issued_date;
|
|
},
|
|
'series',
|
|
'number',
|
|
'contractor_id' => function ($model) {
|
|
return $model->contractor->name ?? '';
|
|
}
|
|
];
|
|
}
|
|
|
|
public function getClassTypeForChangeHistory(): int
|
|
{
|
|
return ChangeHistoryClasses::CLASS_PASSPORT_DATA;
|
|
}
|
|
|
|
public function getIssuedBy(): string
|
|
{
|
|
return $this->contractor->name ?? '';
|
|
}
|
|
|
|
public function getDepartmentCode(): string
|
|
{
|
|
return $this->contractor->subdivision_code ?? '';
|
|
}
|
|
|
|
public function getEntityIdentifier(): ?string
|
|
{
|
|
$doc = ArrayHelper::getValue($this, 'documentTypeDescription');
|
|
return "{$doc} (Серия {$this->series} № {$this->number} выдан {$this->getIssuedBy()})";
|
|
}
|
|
|
|
public function afterValidate()
|
|
{
|
|
(new LoggingAfterValidateHandler())
|
|
->setModel($this)
|
|
->invoke();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function GetOrCreateFromRaw(
|
|
ActiveRecord $model,
|
|
string $series,
|
|
string $number,
|
|
string $issued_date,
|
|
array $doc_organization,
|
|
$document_type_ref,
|
|
array $documentCheckStatusRef = [],
|
|
bool $documentReadOnly = false,
|
|
array $ids_to_ignore = []
|
|
): PassportData {
|
|
$docType = ReferenceTypeManager::GetOrCreateReference(DocumentType::class, $document_type_ref);
|
|
$contractor = ContractorManager::GetOrCreateContractor($doc_organization);
|
|
|
|
$passportDataTableName = PassportData::tableName();
|
|
$local_passport = $model->getPassportData()
|
|
->joinWith(['documentType doc_type'])
|
|
->andWhere(['NOT', ["{$passportDataTableName}.id" => $ids_to_ignore]])
|
|
->andWhere([
|
|
"{$passportDataTableName}.series" => $series,
|
|
"{$passportDataTableName}.number" => $number,
|
|
])
|
|
->andFilterWhere([
|
|
'doc_type.ref_key' => ($docType->ref_key ?? null),
|
|
])
|
|
->one();
|
|
if (!$local_passport) {
|
|
$local_passport = new static();
|
|
static::setQuestionaryLink($local_passport, $model->id);
|
|
}
|
|
|
|
$local_passport->read_only = $documentReadOnly;
|
|
$local_passport->setDocumentCheckStatusFrom1CData($documentCheckStatusRef);
|
|
|
|
$local_passport->setScenarioForUpdateFromRaw();
|
|
$local_passport->attributes = [
|
|
'series' => $series,
|
|
'number' => $number,
|
|
'document_type_id' => ($docType->id ?? null),
|
|
'issued_date' => $issued_date,
|
|
'contractor_id' => ($contractor->id ?? null)
|
|
];
|
|
$local_passport->archive = false;
|
|
DraftsManager::SuspendHistory($local_passport);
|
|
if (!$local_passport->save(false)) {
|
|
throw new RecordNotValid($local_passport);
|
|
}
|
|
|
|
return $local_passport;
|
|
}
|
|
|
|
public function setScenarioForUpdateFromRaw()
|
|
{
|
|
$this->scenario = PassportData::SCENARIO_GET_ANKETA;
|
|
}
|
|
|
|
protected static function setQuestionaryLink(PassportData $model, ?int $questionary_id)
|
|
{
|
|
$model->questionary_id = $questionary_id;
|
|
}
|
|
|
|
public function getIdentityString(): string
|
|
{
|
|
$doc_type_uid = ArrayHelper::getValue($this, 'documentType.ref_key', '');
|
|
return "{$this->series}_{$this->number}_{$doc_type_uid}";
|
|
}
|
|
|
|
public function getDocumentTypeDescription()
|
|
{
|
|
return ArrayHelper::getValue($this, 'documentType.description');
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getClientFormName(): string
|
|
{
|
|
return mb_strtolower($this->formName());
|
|
}
|
|
|
|
public function getPropsToCompare(): array
|
|
{
|
|
return ArrayHelper::merge(
|
|
array_diff(array_keys($this->attributes), ['document_type_id']),
|
|
['documentTypeDescription']
|
|
);
|
|
}
|
|
|
|
public static function getTableLink(): string
|
|
{
|
|
return 'passport_attachment';
|
|
}
|
|
|
|
public static function getEntityTableLinkAttribute(): string
|
|
{
|
|
return 'passport_id';
|
|
}
|
|
|
|
public static function getAttachmentTableLinkAttribute(): string
|
|
{
|
|
return "attachment_id";
|
|
}
|
|
|
|
public static function getModel(): string
|
|
{
|
|
return get_called_class();
|
|
}
|
|
|
|
public static function getDbTableSchema(): TableSchema
|
|
{
|
|
return self::getTableSchema();
|
|
}
|
|
|
|
public function getAttachmentType(): ?AttachmentType
|
|
{
|
|
return AttachmentManager::GetSystemAttachmentType(AttachmentType::SYSTEM_TYPE_IDENTITY_DOCUMENT);
|
|
}
|
|
|
|
public function getAttachments(): ActiveQuery
|
|
{
|
|
return $this->getRawAttachments()
|
|
->andOnCondition([
|
|
Attachment::tableName() . '.deleted' => false,
|
|
]);
|
|
}
|
|
|
|
public function getRawAttachments(): ActiveQuery
|
|
{
|
|
return $this->hasMany(Attachment::class, ['id' => self::getAttachmentTableLinkAttribute()])
|
|
->viaTable(self::getTableLink(), [
|
|
self::getEntityTableLinkAttribute() => 'id'
|
|
]);
|
|
}
|
|
|
|
public function getName(): string
|
|
{
|
|
$name = Yii::t('abiturient/questionary/passport-data', 'Название сущности документов удостоверяющих личность поступающего: `Документ удостоверяющий личность`');
|
|
return "{$name} {$this->getEntityIdentifier()}";
|
|
}
|
|
|
|
public function stringify(): string
|
|
{
|
|
return $this->getName();
|
|
}
|
|
|
|
public function getAttachmentCollection(): ?AttachedEntityAttachmentCollection
|
|
{
|
|
return new AttachedEntityAttachmentCollection($this->getUserInstance(), $this, $this->getAttachmentType(), $this->attachments, $this->formName(), 'file');
|
|
}
|
|
|
|
public function getAttachmentConnectors(): array
|
|
{
|
|
return [
|
|
'questionary_id' => $this->abiturientQuestionary->id
|
|
];
|
|
}
|
|
|
|
public function getUserInstance(): User
|
|
{
|
|
return ArrayHelper::getValue($this, 'abiturientQuestionary.user') ?: new User();
|
|
}
|
|
|
|
public function getRelationsInfo(): array
|
|
{
|
|
return [
|
|
new AttachmentsRelationPresenter('attachments', [
|
|
'parent_instance' => $this,
|
|
]),
|
|
];
|
|
}
|
|
|
|
public function beforeDelete()
|
|
{
|
|
if (parent::beforeDelete()) {
|
|
AttachmentManager::unlinkAllAttachment($this);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function getIsActuallyNewRecord(): bool
|
|
{
|
|
return $this->_new_record;
|
|
}
|
|
|
|
public function getAttachedFilesInfo(): array
|
|
{
|
|
$files = [];
|
|
foreach ($this->attachments as $achievement) {
|
|
$files[] = [
|
|
$achievement,
|
|
ArrayHelper::getValue($this, 'documentType'),
|
|
null
|
|
];
|
|
}
|
|
return $files;
|
|
}
|
|
|
|
public function getContractor(): ActiveQuery
|
|
{
|
|
return $this->hasOne(Contractor::class, ['id' => 'contractor_id']);
|
|
}
|
|
|
|
public function isNotRegularIssueDate(): bool
|
|
{
|
|
$questionary = $this->abiturientQuestionary;
|
|
if ($questionary && $questionary->personalData) {
|
|
$issued_date_days = strtotime($this->issued_date) / (60 * 60 * 24);
|
|
$birthdate_days = strtotime($questionary->personalData->birthdate) / (60 * 60 * 24);
|
|
$diff_days = $issued_date_days - $birthdate_days;
|
|
if (0 < $diff_days - 365 * 14 && $diff_days - 365 * 14 <= 100) {
|
|
return false;
|
|
}
|
|
if (0 < $diff_days - 365 * 20 && $diff_days - 365 * 20 <= 100) {
|
|
return false;
|
|
}
|
|
if (0 < $diff_days - 365 * 45 && $diff_days - 365 * 45 <= 100) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static function getDocumentTypePropertyName(): string
|
|
{
|
|
return 'documentType';
|
|
}
|
|
|
|
public static function getSubdivisionCodePropertyName(): string
|
|
{
|
|
return '';
|
|
}
|
|
|
|
public static function getIssuedDatePropertyName(): string
|
|
{
|
|
return 'issued_date';
|
|
}
|
|
|
|
public static function getDateOfEndPropertyName(): string
|
|
{
|
|
return '';
|
|
}
|
|
|
|
public static function getAdditionalPropertyName(): string
|
|
{
|
|
return '';
|
|
}
|
|
|
|
public static function getIssuedByPropertyName(): string
|
|
{
|
|
return 'contractor_id';
|
|
}
|
|
|
|
public static function getDocumentSeriesPropertyName(): string
|
|
{
|
|
return 'series';
|
|
}
|
|
|
|
public static function getDocumentNumberPropertyName(): string
|
|
{
|
|
return 'number';
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function beforeSave($insert)
|
|
{
|
|
if (!parent::beforeSave($insert)) {
|
|
return false;
|
|
}
|
|
|
|
if (!$this->fillDocumentCheckStatusIfNotVerified()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|