1109 lines
37 KiB
PHP
1109 lines
37 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\models;
|
||
|
||
use yii;
|
||
use yii\web\IdentityInterface;
|
||
|
||
use carono\exchange1c\interfaces\PartnerInterface;
|
||
|
||
use app\models\Dellin;
|
||
use app\models\traits\SearchByEdge;
|
||
|
||
use yii\web\UploadedFile;
|
||
|
||
/**
|
||
* Аккаунт
|
||
*
|
||
* Реализует аккаунты пользователей и поставщиков
|
||
*/
|
||
class Account extends Document implements IdentityInterface, PartnerInterface
|
||
{
|
||
use SearchByEdge;
|
||
|
||
/**
|
||
* Имя коллекции
|
||
*/
|
||
public static function collectionName(): string
|
||
{
|
||
return 'account';
|
||
}
|
||
|
||
/**
|
||
* Свойства
|
||
*/
|
||
public function attributes(): array
|
||
{
|
||
return array_merge(
|
||
parent::attributes(),
|
||
[
|
||
'name',
|
||
'mail',
|
||
'desc',
|
||
'indx',
|
||
'pswd',
|
||
'simc',
|
||
'boss',
|
||
'sity',
|
||
'zone',
|
||
'comp',
|
||
'cntc',
|
||
'taxn',
|
||
'cntg',
|
||
'fadd',
|
||
'ladd',
|
||
'chck',
|
||
'onec',
|
||
'opts',
|
||
'agnt',
|
||
'type',
|
||
'vrfy',
|
||
'geol',
|
||
'auth',
|
||
'acpt',
|
||
'chpk'
|
||
]
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Метки свойств
|
||
*/
|
||
public function attributeLabels(): array
|
||
{
|
||
return array_merge(
|
||
parent::attributeLabels(),
|
||
[
|
||
'name' => 'Контактное лицо',
|
||
'mail' => 'Почта',
|
||
'desc' => 'Описание',
|
||
'indx' => 'Псевдоанонимный идентификатор',
|
||
'pswd' => 'Пароль',
|
||
'simc' => 'Номер',
|
||
'boss' => 'Директор',
|
||
'sity' => 'Город',
|
||
'zone' => 'Часовой пояс',
|
||
'comp' => 'Компания',
|
||
'cntc' => 'Контакты',
|
||
'taxn' => 'ИНН',
|
||
'cntg' => 'КПП',
|
||
'fadd' => 'Фактический адрес',
|
||
'ladd' => 'Юридический адрес',
|
||
'chck' => 'Расчетный счет',
|
||
'onec' => 'Данные 1C',
|
||
'opts' => 'Параметры',
|
||
'agnt' => 'Агент (поставщик)',
|
||
'type' => 'Тип аккаунта',
|
||
'vrfy' => 'Статус подтверждения владением почты',
|
||
'geol' => 'Геолокация',
|
||
'auth' => 'Аутентификационный хеш',
|
||
'acpt' => 'Согласие с офертой',
|
||
'chpk' => 'Ключ для смены пароля'
|
||
]
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Правила
|
||
*/
|
||
public function rules(): array
|
||
{
|
||
return array_merge(
|
||
parent::rules(),
|
||
[
|
||
[
|
||
[
|
||
'mail',
|
||
'pswd'
|
||
],
|
||
'required',
|
||
'message' => 'Заполните поле'
|
||
],
|
||
[
|
||
'mail',
|
||
'email'
|
||
],
|
||
[
|
||
[
|
||
'mail',
|
||
'indx',
|
||
'comp',
|
||
'simc'
|
||
],
|
||
'unique',
|
||
'message' => 'Атрибут {attribute} должен иметь уникальное значение'
|
||
],
|
||
[
|
||
[
|
||
'indx',
|
||
'zone'
|
||
],
|
||
'string'
|
||
],
|
||
[
|
||
'vrfy',
|
||
'validateVrfyUnique'
|
||
],
|
||
[
|
||
'taxn',
|
||
'integer',
|
||
'min' => 0,
|
||
'max' => 999999999999
|
||
],
|
||
[
|
||
'cntg',
|
||
'integer',
|
||
'min' => 0,
|
||
'max' => 99999999999999999999
|
||
],
|
||
[
|
||
'ladd',
|
||
'string',
|
||
'length' => [0, 200]
|
||
],
|
||
[
|
||
[
|
||
'desc',
|
||
'cntc'
|
||
],
|
||
'string',
|
||
'length' => [0, 500]
|
||
],
|
||
[
|
||
'simc',
|
||
'integer',
|
||
'min' => 0,
|
||
'max' => 999999999999999999999999999999
|
||
],
|
||
[
|
||
'comp',
|
||
'string',
|
||
'length' => [0, 40]
|
||
],
|
||
[
|
||
[
|
||
'name',
|
||
'boss'
|
||
],
|
||
'string',
|
||
'length' => [0, 100]
|
||
]
|
||
]
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Перед сохранением
|
||
*
|
||
* @todo Подождать обновление от ебаного Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public function beforeSave($data): bool
|
||
{
|
||
if (parent::beforeSave($data)) {
|
||
if ($this->isNewRecord) {
|
||
$this->mail = mb_strtolower($this->mail);
|
||
$this->auth = yii::$app->security->generateRandomString();
|
||
$this->vrfy = yii::$app->security->generateRandomString();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Отправка сообщения для генерации нового пароля
|
||
*/
|
||
public static function restoreSend(string $mail): bool
|
||
{
|
||
if (($account = self::findByMail($mail)) instanceof self) {
|
||
// Найден аккаунт
|
||
|
||
// Запись ключа для аутентификации
|
||
$account->chpk = yii::$app->security->generateRandomString();
|
||
|
||
if ($account->update()) {
|
||
// Удалось обновить аккаунт
|
||
|
||
// Отправка письма
|
||
yii::$app->mail_system->compose()
|
||
->setFrom(yii::$app->params['mail']['system'])
|
||
->setTo($account->mail)
|
||
->setSubject('Подтвердите сброс пароля')
|
||
->setHtmlBody(yii::$app->controller->renderPartial('/mails/restore', ['id' => $account->_key, 'chpk' => $account->chpk]))
|
||
->send();
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Генерация нового пароля
|
||
*/
|
||
public function restoreGenerate(): void
|
||
{
|
||
// Удаление ключа
|
||
$this->chpk = null;
|
||
|
||
// Генерация пароля
|
||
$this->pswd = self::passwordGenerate();
|
||
|
||
if ($this->update()) {
|
||
// Удалось обновить аккаунт
|
||
|
||
// Отправка письма
|
||
yii::$app->mail_system->compose()
|
||
->setFrom(yii::$app->params['mail']['system'])
|
||
->setTo($this->mail)
|
||
->setSubject('Генерация пароля')
|
||
->setHtmlBody(yii::$app->controller->renderPartial('/mails/password', ['pswd' => $this->pswd]))
|
||
->send();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Чтение полей для экспорта из 1С
|
||
*/
|
||
public function getExportFields1c($context = null): array
|
||
{
|
||
return [];
|
||
}
|
||
|
||
/**
|
||
* Чтение идентификатора
|
||
*
|
||
* @see IdentityInterface
|
||
*/
|
||
public function getId(): string
|
||
{
|
||
return self::collectionName() . '/' . $this->_key;
|
||
}
|
||
|
||
/**
|
||
* Чтение идентификатора
|
||
*/
|
||
public function readId(): string
|
||
{
|
||
return $this->getId();
|
||
}
|
||
|
||
/**
|
||
* Чтение аутентификационного ключа
|
||
*/
|
||
public function getAuthKey(): string
|
||
{
|
||
return $this->auth;
|
||
}
|
||
|
||
/**
|
||
* Идентификация
|
||
*
|
||
* @todo Подождать обновление от ебаного Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public static function findIdentity($_id): self
|
||
{
|
||
return static::findById($_id);
|
||
}
|
||
|
||
/**
|
||
* Поиск по ключу
|
||
*
|
||
* @todo Подождать обновление от ебаного Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public static function findIdentityByAccessToken($pass, $type = null): self
|
||
{
|
||
return static::findOne(['pass' => $pass]);
|
||
}
|
||
|
||
/**
|
||
* Поиск по почте
|
||
*
|
||
* @todo Подождать обновление Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public static function findByMail($mail): ?self
|
||
{
|
||
return static::findOne(['mail' => $mail]);
|
||
}
|
||
|
||
/**
|
||
* Поиск по статусу активации почты
|
||
*
|
||
* @todo Подождать обновление Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public static function findByVrfy($vrfy): ?self
|
||
{
|
||
return static::findOne(['vrfy' => $vrfy]);
|
||
}
|
||
|
||
/**
|
||
* Поиск по идентификатору
|
||
*
|
||
* @todo Подождать обновление Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public static function findById($_id): self
|
||
{
|
||
return static::searchById($_id);
|
||
}
|
||
|
||
/**
|
||
* Чтение всех модераторов
|
||
*/
|
||
public static function readAllModerators(): array
|
||
{
|
||
return static::find()->where(['type' => 'moderator'])->all();
|
||
}
|
||
|
||
/**
|
||
* Чтение всех администраторов
|
||
*/
|
||
public static function readAllAdministrators(): array
|
||
{
|
||
return static::find()->where(['type' => 'administrator'])->all();
|
||
}
|
||
|
||
/**
|
||
* Чтение всех уполномоченных аккаунтов
|
||
*/
|
||
public static function readAllAuthorizeds(): array
|
||
{
|
||
return static::find()->where(['type' => 'moderator'])->orWhere(['type' => 'administrator'])->all();
|
||
}
|
||
|
||
/**
|
||
* Подтверждение регистрации
|
||
*/
|
||
public static function verification(string $vrfy, bool $auth = false): bool
|
||
{
|
||
if ($account = static::findByVrfy($vrfy)) {
|
||
// Аккаунт найден
|
||
|
||
// Запись в буфер
|
||
$account->vrfy = true;
|
||
|
||
// Отправка изменений
|
||
$updated = $account->update() > 0;
|
||
|
||
if ($updated && $auth) {
|
||
// Регистрация была подтверждена, а так же запрошена автоматическая аутентификация
|
||
|
||
// Аутентификация
|
||
yii::$app->user->login($account, true ? 3600 * 24 * 30 : 0);
|
||
}
|
||
|
||
return $updated;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Проверка пароля с хешированием
|
||
*/
|
||
public function validatePasswordWithHash(string $pswd): bool
|
||
{
|
||
return yii::$app->security->validatePassword($pswd, $this->pswd);
|
||
}
|
||
|
||
/**
|
||
* Проверка пароля без хеширования
|
||
*/
|
||
public function validatePasswordWithoutHash(string $pswd): bool
|
||
{
|
||
return $pswd === $this->pswd;
|
||
}
|
||
|
||
/**
|
||
* Проверка аутентификационного ключа
|
||
*
|
||
* @todo Подождать обновление Yii2 и добавить
|
||
* проверку типов передаваемых параметров
|
||
*/
|
||
public function validateAuthKey($auth): bool
|
||
{
|
||
return $this->getAuthKey() === $auth;
|
||
}
|
||
|
||
/**
|
||
* Проверка почты
|
||
*/
|
||
public static function validateMail(string $mail): bool
|
||
{
|
||
if ($account = static::findByMail($mail)) {
|
||
// Почта найдена в базе данных
|
||
|
||
if (isset($account) && $account->vrfy === true) {
|
||
// Регистрация подтверждена
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Проверка статуса подтверждения регистрации
|
||
*/
|
||
public static function validateVrfy(string $vrfy): bool
|
||
{
|
||
if ($account = static::findByVrfy($vrfy)) {
|
||
// Статус найден в базе данных
|
||
|
||
if ($account->vrfy === true) {
|
||
// Регистрация подтверждена
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Проверка данных для поля подтверждения регистрации
|
||
*/
|
||
public function validateVrfyUnique($attribute, $params)
|
||
{
|
||
if (!$this->hasErrors()) {
|
||
// Проблем нет
|
||
|
||
if ($attribute !== true && $this->validateVrfy($attribute)) {
|
||
// Проверка не пройдена
|
||
|
||
$this->addError($attribute, 'Ключ подтверждения регистрации уже используется');
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Записать параметр
|
||
*
|
||
* @param string $name Название параметра
|
||
* @param mixed $value Значение параметра
|
||
*/
|
||
public function writeOption(string $name, mixed $value = null): bool
|
||
{
|
||
// Запись
|
||
$this->opts = [$name => $value] + $this->opts;
|
||
|
||
// Отправка
|
||
return $this->update() > 0;
|
||
}
|
||
|
||
/**
|
||
* Удалить параметр
|
||
*
|
||
* @param string $name Название параметра
|
||
*/
|
||
public function deleteOption(string $name): bool
|
||
{
|
||
// Удаление
|
||
unset($this->opts[$name]);
|
||
|
||
// Отправка
|
||
return $this->update() > 0;
|
||
}
|
||
|
||
/**
|
||
* Генерация списка городов
|
||
*
|
||
* Актуальное (выбранное, активное) значение записывается первым
|
||
*/
|
||
public function genListCity(): void
|
||
{
|
||
// $browser = new Dellin();
|
||
|
||
// $request = $browser->get('https://api.github.com/user', [
|
||
// 'auth' => ['user', 'pass']
|
||
// ]);
|
||
}
|
||
|
||
/**
|
||
* Генерация списка OEM-номеров
|
||
*
|
||
* Актуальное (выбранное, активное) значение записывается первым
|
||
*
|
||
* @param array $supplies Необработанный список поставок
|
||
*/
|
||
public function genListOem(array $supplies): array
|
||
{
|
||
// Инициализация
|
||
$list = [];
|
||
|
||
foreach ($supplies as $supply) {
|
||
// Перебор поставок
|
||
if (in_array($supply['ЗначенияСвойства']['Ид'], $list, true)) {
|
||
// Если встретился дубликат (исполняется очень часто)
|
||
|
||
continue;
|
||
}
|
||
|
||
// Генерация
|
||
empty($supply['ЗначенияСвойства']['Наименование']) or $list[$supply['ЗначенияСвойства']['Ид']] = $supply['ЗначенияСвойства']['Наименование'];
|
||
}
|
||
|
||
return $this->syncListWithSettings($list, 'import_supplies_oem');
|
||
}
|
||
|
||
/**
|
||
* Генерация списка терминалов из ДеловыеЛинии для получателя
|
||
*
|
||
* Актуальное (выбранное, активное) значение записывается первым
|
||
*
|
||
* @param array Необработанный список терминалов
|
||
*/
|
||
public function genListTerminalsTo(): array
|
||
{
|
||
// Инициализация
|
||
$list = [];
|
||
|
||
$terminals = Terminal::readAll();
|
||
|
||
foreach ($terminals as $terminal) {
|
||
// Перебор городов
|
||
|
||
if (in_array($terminal->dell, $list, true)) {
|
||
// Если встретился дубликат (исполняется очень часто)
|
||
|
||
continue;
|
||
}
|
||
|
||
// Запись
|
||
empty($terminal->city) && empty($terminal->strt) && empty($terminal->hous)
|
||
or $list[$terminal->dell] = (empty($terminal->city) ? '' : "г. $terminal->city") . (empty($terminal->strt) ? '' : ", ул. $terminal->strt") . (empty($terminal->hous) ? '' : ", д. $terminal->hous") . (empty($terminal->offs) ? '' : ", оф. $terminal->offs") . (empty($terminal->comm) ? '' : " ($terminal->comm)");
|
||
}
|
||
|
||
return $this->syncListWithSettings($list, 'delivery_to_terminal');
|
||
}
|
||
|
||
/**
|
||
* Синхронизация списка вариантов параметра с текущим значением из настроек
|
||
*
|
||
* @param array &$list Список
|
||
* @param string $var Название параметра
|
||
*
|
||
* @return array Сортированный список
|
||
*/
|
||
protected function syncListWithSettings(array &$list, string $var): array
|
||
{
|
||
// Инициализация текущего значения параметра в начале массива
|
||
if (isset($this->opts[$var])) {
|
||
// Параметр найден в настройках аккаунта
|
||
|
||
if (isset($list[$this->opts[$var]])) {
|
||
// Найдено совпадение сохранённого параметра с полученным списком из поставок
|
||
|
||
// Буфер для сохранения параметра
|
||
$buffer = $list[$this->opts[$var]];
|
||
|
||
// Удаление параметра
|
||
unset($list[$this->opts[$var]]);
|
||
|
||
// Сохранение параметра в начале массива
|
||
$list = [$this->opts[$var] => $buffer] + $list;
|
||
} else {
|
||
// Совпадение не найдено
|
||
|
||
// Сохранение параметра из данных аккаунта в начале массива
|
||
$list = [$this->opts[$var] => $this->opts[$var]] + $list;
|
||
}
|
||
} else {
|
||
// Параметр $var не найден в настройках аккаунта
|
||
|
||
// Сохранение параметра из данных аккаунта в начале массива
|
||
$list = ['Выберите' => 'Выберите'] + $list;
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* Генерация псевдоанонимных индексов
|
||
*
|
||
* @param [int] $accounts Массив аккаунтов
|
||
* @param bool $force Перезаписывать, если существует
|
||
*
|
||
* @return int Количество успешно обработанных аккаунтов
|
||
*/
|
||
public static function generateIndexes(array $accounts, bool $force = false): int
|
||
{
|
||
// Инициализация
|
||
$amount = 0;
|
||
|
||
// Функция для конвертации цифр в буквы
|
||
$int_to_string = function (int $target): string {
|
||
// $alphabet = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я'];
|
||
$alphabet = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Ю', 'Я'];
|
||
|
||
return $alphabet[$target];
|
||
};
|
||
|
||
// Реестр запрещённых индексов
|
||
$registry = [
|
||
'ЧМО',
|
||
'ХЕР',
|
||
'ХУЙ',
|
||
'БЛЯ',
|
||
'СУК',
|
||
'СУЧ',
|
||
'ЖОП',
|
||
'ЛОХ'
|
||
];
|
||
|
||
foreach ($accounts as $account) {
|
||
// Перебор запрошенных аккаунтов
|
||
|
||
if ($force || empty($account->indx)) {
|
||
// Запись только тех аккаунтов у кого не инициализирован индекс, либо если указана перезапись
|
||
|
||
// Повтор генерации
|
||
regenerate_index:
|
||
|
||
// Генерация
|
||
$account->indx = $int_to_string(random_int(0, 27)) . $int_to_string(random_int(0, 27)) . $int_to_string(random_int(0, 27));
|
||
|
||
if (in_array($account->indx, $registry)) {
|
||
// Сгенерированный индекс обнаружено в реестре запрещённых индексов
|
||
|
||
// Повтор генерации
|
||
goto regenerate_index;
|
||
}
|
||
|
||
// Запись
|
||
if ($account->save()) {
|
||
// Аккаунт сохранён (в базе данных это поле проверяется на уникальность)
|
||
|
||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||
// Вызов из терминала
|
||
|
||
echo "Удалось сохранить аккаунт с псевдоанонимным идентификатором $account->indx" . PHP_EOL;
|
||
}
|
||
|
||
// Запись операции в счётчик
|
||
$amount++;
|
||
} else {
|
||
// Аккаунт не сохранен (подразумевается несовпадение идентификаторов)
|
||
|
||
if (yii::$app->getRequest()->isConsoleRequest) {
|
||
// Вызов из терминала
|
||
|
||
echo "Не удалось сохранить аккаунт с псевдоанонимным идентификатором $account->indx" . PHP_EOL;
|
||
}
|
||
|
||
goto regenerate_index;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $amount;
|
||
}
|
||
|
||
/**
|
||
* Найти по идентификатору поставки
|
||
*
|
||
* @param string|null $_id Идентификатор поставки
|
||
*
|
||
* @return self|null Аккаунт владельца
|
||
*/
|
||
public static function searchBySupplyId(string $_id): ?array
|
||
{
|
||
return static::searchByEdge(
|
||
from: 'supply',
|
||
to: 'account',
|
||
edge: 'account_edge_supply',
|
||
direction: 'OUTBOUND',
|
||
subquery_where: [
|
||
[
|
||
'account_edge_supply._to == "' . $_id . '"'
|
||
]
|
||
],
|
||
subquery_select: 'account',
|
||
where: 'account_edge_supply[0]._id != null',
|
||
select: 'account_edge_supply[0]',
|
||
limit: 1
|
||
)[0] ?? null;
|
||
}
|
||
|
||
/**
|
||
* Генерация текста обозначающего статус аккаунта на русском языке
|
||
*
|
||
* @return string Статус аккаунта
|
||
*/
|
||
public function statusLabel(): string
|
||
{
|
||
return match ($this->type) {
|
||
'administrator', 'admin' => 'Администратор',
|
||
'moderator', 'moder' => 'Модератор',
|
||
'supplier' => 'Поставщик',
|
||
default => 'Покупатель',
|
||
};
|
||
}
|
||
|
||
public function sendMailVerify(): bool
|
||
{
|
||
if (isset($this->mail, $this->vrfy) && !$this->validateVrfy($this->vrfy)) {
|
||
// Данные инициализированы, а регистрация ещё не была подтверждена
|
||
|
||
// Отправка письма
|
||
yii::$app->mail_system->compose()
|
||
->setFrom(yii::$app->params['mail']['system'])
|
||
->setTo($this->mail)
|
||
->setSubject('Подтверждение регистрации')
|
||
->setHtmlBody(yii::$app->controller->renderPartial('/mails/verify', ['vrfy' => $this->vrfy, 'password' => $this->pswd]))
|
||
->send();
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public function sendMailDecline(string $reason = 'Проблема с данными'): bool
|
||
{
|
||
// Отправка письма
|
||
yii::$app->mail_system->compose()
|
||
->setFrom(yii::$app->params['mail']['system'])
|
||
->setTo($this->mail)
|
||
->setSubject('Отказано в регистрации')
|
||
->setHtmlBody(yii::$app->controller->renderPartial('/mails/suppliers/decline', ['reason' => $reason]))
|
||
->send();
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Инициализация пароля
|
||
*/
|
||
public function passwordInit(): bool
|
||
{
|
||
if (empty($this->pswd) || $this->pswd === 'undefined') {
|
||
// Пароль не инициализирован
|
||
|
||
// Генерация пароля
|
||
$this->pswd = self::passwordGenerate();
|
||
|
||
// Возврат
|
||
return true;
|
||
}
|
||
|
||
// Возврат (подразумевается неудача)
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Гениальный генератор пароля
|
||
*
|
||
* 35 * 19 * 9 = 5985 комбинаций
|
||
*
|
||
* @return string|null
|
||
*/
|
||
public static function passwordGenerate(): ?string
|
||
{
|
||
$password = '';
|
||
|
||
$arr = array(
|
||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
|
||
);
|
||
|
||
for ($i = 0; $i < 6; $i++) {
|
||
$password .= $arr[random_int(0, count($arr) - 1)];
|
||
}
|
||
|
||
return $password;
|
||
// return match (rand(1, 35)) {
|
||
// 1 => 'салазки',
|
||
// 2 => 'запчасти',
|
||
// 3 => 'инструменты',
|
||
// 4 => 'детали',
|
||
// 5 => 'компоненты',
|
||
// 6 => 'ремни',
|
||
// 7 => 'шестерни',
|
||
// 8 => 'блоки',
|
||
// 9 => 'коронки',
|
||
// 10 => 'вал',
|
||
// 11 => 'пыльник',
|
||
// 12 => 'шкив',
|
||
// 13 => 'станок',
|
||
// 14 => 'сальник',
|
||
// 15 => 'кольцо',
|
||
// 16 => 'цепь',
|
||
// 17 => 'редуктор',
|
||
// 18 => 'фильтр',
|
||
// 19 => 'клапан',
|
||
// 20 => 'фару',
|
||
// 21 => 'мотор',
|
||
// 22 => 'подшипник',
|
||
// 23 => 'болт',
|
||
// 24 => 'стартер',
|
||
// 25 => 'двигатель',
|
||
// 26 => 'трубку',
|
||
// 27 => 'прокладку',
|
||
// 28 => 'помпу',
|
||
// 29 => 'запчасть',
|
||
// 30 => 'втулку',
|
||
// 31 => 'уплотнение',
|
||
// 32 => 'ролик',
|
||
// 33 => 'датчик',
|
||
// 34 => 'насос',
|
||
// default => 'машину'
|
||
// }
|
||
// . ' ' . match (rand(1, 15)) {
|
||
// 1 => 'забыли',
|
||
// 2 => 'испортили',
|
||
// 3 => 'забрали',
|
||
// 4 => 'порвали',
|
||
// 5 => 'украли',
|
||
// 6 => 'обменяли',
|
||
// 7 => 'угнали',
|
||
// 8 => 'взорвали',
|
||
// 9 => 'поломали',
|
||
// 1 => 'доломали',
|
||
// 11 => 'утопили',
|
||
// 12 => 'испортили',
|
||
// 13 => 'добили',
|
||
// 14 => 'разбили',
|
||
// 15 => 'сорвали',
|
||
// default => 'сломали'
|
||
// }
|
||
// . ' ' . match (rand(1, 9)) {
|
||
// 1 => 'закажу',
|
||
// 2 => 'найду',
|
||
// 3 => 'отыщу',
|
||
// 4 => 'запрошу',
|
||
// 5 => 'поищу',
|
||
// 6 => 'оформлю',
|
||
// 7 => 'заменю',
|
||
// 8 => 'поменяю',
|
||
// default => 'куплю'
|
||
// }
|
||
// . ' в скиллпартс';
|
||
}
|
||
|
||
/**
|
||
* Пересоздать ключ подтверждения регистрации и пароль к аккаунту
|
||
*
|
||
* @return bool
|
||
*/
|
||
public function verifyRegenerate(): bool
|
||
{
|
||
$this->pswd = static::passwordGenerate();
|
||
$this->vrfy = yii::$app->security->generateRandomString();
|
||
|
||
return $this->update() > 0 ? true : false;
|
||
}
|
||
|
||
/**
|
||
* Запись поставщика
|
||
*
|
||
* @return array
|
||
*/
|
||
public static function writeSupplier(string $name, string $phone, string $mail, UploadedFile $file): ?static
|
||
{
|
||
// Инициализация
|
||
$account = new static;
|
||
|
||
// Настройка
|
||
$account->agnt = true;
|
||
$account->name = $name;
|
||
$account->boss = $name;
|
||
$account->simc = $phone;
|
||
$account->mail = $mail;
|
||
$account->type = 'requested';
|
||
|
||
// Генерация пароля
|
||
$account->passwordInit();
|
||
|
||
if ($account->save()) {
|
||
// Удалось сохранить аккаунт
|
||
|
||
// Инициализация индекса
|
||
Account::generateIndexes([$account]);
|
||
|
||
if (!file_exists($path = YII_PATH_PUBLIC . "/../assets/accounts/$account->_key/files")) {
|
||
// Директория для хранения документов не найдена
|
||
|
||
if (!mkdir($path, 0775, true)) {
|
||
// Не удалось записать директорию
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Перенос файла из временной директории
|
||
copy($file->tempName, $path .= "/$file->name");
|
||
|
||
// Запись в журнал
|
||
$account->journal('request to become a supplier', [
|
||
'name' => $name,
|
||
'phone' => $phone,
|
||
'mail' => $mail,
|
||
'file' => [
|
||
'path' => $path,
|
||
'uri' => "/$account->_key/files/$file->name"
|
||
]
|
||
]);
|
||
|
||
// Отправка уведомлений
|
||
Notification::_write(yii::$app->controller->renderPartial('/notification/system/suppliers/request', ['_key' => $account->_key]), html: true, account: '@authorized');
|
||
|
||
return $account;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Поиск заявок на регистрацию поставщиков
|
||
*
|
||
* @return array
|
||
*/
|
||
public static function searchSuppliersRequests(int $amount = 3, int $page, array $order = ['DESC']): array
|
||
{
|
||
return self::find()->where(['agnt' => true, 'type' => 'requested'])->limit($amount)->offset($amount * ($page - 1))->orderBy($order)->all();
|
||
}
|
||
|
||
/**
|
||
* Инициализация аккаунта для контроллера
|
||
*
|
||
* @param static|null $account Аккаунт
|
||
*/
|
||
public static function initAccount(Account|string|int $account = null): ?static
|
||
{
|
||
if (is_null($account)) {
|
||
// Данные аккаунта не переданы
|
||
|
||
if (empty(yii::$app->user) || yii::$app->user->isGuest) {
|
||
// Аккаунт не аутентифицирован
|
||
} else {
|
||
// Аккаунт аутентифицирован
|
||
|
||
// Инициализация
|
||
$account = yii::$app->user->identity;
|
||
|
||
return $account;
|
||
}
|
||
} else {
|
||
if ($account instanceof Account) {
|
||
// Передана инстанция аккаунта
|
||
|
||
return $account;
|
||
} else if (is_int($account)) {
|
||
// Передан идентификатор (_key) аккаунта (подразумевается)
|
||
|
||
// Инициализация (поиск в базе данных)
|
||
if ($account = Account::searchById(Account::collectionName() . "/$account")) {
|
||
// Удалось инициализировать аккаунт
|
||
|
||
return $account;
|
||
}
|
||
} else if (is_string($account)) {
|
||
// Передан идентификатор документа (_id) (подразумевается)
|
||
|
||
// Инициализация (поиск в базе данных)
|
||
if ($account = Account::searchById($account)) {
|
||
// Удалось инициализировать аккаунт
|
||
|
||
return $account;
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Проверка на то, что аккаунт является администраторрм
|
||
*
|
||
* @param static|null $account Аккаунт
|
||
*/
|
||
public static function isAdmin($account = null): bool
|
||
{
|
||
if ($account = self::initAccount($account)) {
|
||
// Аккаунт инициализирован
|
||
|
||
if ($account->type === 'administrator') {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Проверка на то, что аккаунт является модератором
|
||
*
|
||
* @param static|null $account Аккаунт
|
||
*/
|
||
public static function isModer($account = null): bool
|
||
{
|
||
if ($account = self::initAccount($account)) {
|
||
// Инициализирован аккаунт
|
||
|
||
if ($account->type === 'moderator') {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Проверка на то, что аккаунт имеет минимальный доступ
|
||
*
|
||
* @param static|null $account Аккаунт
|
||
*/
|
||
public static function isMinimalAuthorized($account = null): bool
|
||
{
|
||
return self::isModer($account) || self::isAdmin($account);
|
||
}
|
||
|
||
/**
|
||
* Сгенерировать тип аккаунта на русском языке
|
||
*/
|
||
public function type(): string
|
||
{
|
||
return match ($this->type) {
|
||
'administrator' => 'Администратор',
|
||
'moderator' => 'Модератор',
|
||
'user' => 'Пользователь',
|
||
'requested' => 'Запрошен',
|
||
default => 'Неизвестно'
|
||
};
|
||
}
|
||
|
||
public static function filled($account = null): bool|self
|
||
{
|
||
if ($account = self::initAccount($account)) {
|
||
// Инициализирован аккаунт
|
||
|
||
// Проверка на заполненность обязательных полей
|
||
if (empty($account->name)) $account->addError('name', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->boss)) $account->addError('boss', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->simc)) $account->addError('simc', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->comp)) $account->addError('comp', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->mail)) $account->addError('mail', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->taxn)) $account->addError('taxn', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->cntg)) $account->addError('cntg', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->fadd)) $account->addError('fadd', 'Не заполнено необходимое поле для заказа');
|
||
if (empty($account->ladd)) $account->addError('ladd', 'Не заполнено необходимое поле для заказа');
|
||
|
||
return $account->hasErrors() ? $account : true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|