This commit is contained in:
Kavalar 2023-12-04 20:24:06 +03:00
commit d50f5e8031
129 changed files with 5238 additions and 891 deletions

View File

@ -1,4 +1,4 @@
<?php <?php
return [ return [
'adminEmail' => 'admin@example.com', 'adminEmail' => 'chancellery@itguild.info',
]; ];

View File

@ -0,0 +1,127 @@
<?php
namespace backend\modules\project\controllers;
use Yii;
use backend\modules\project\models\ProjectRole;
use backend\modules\project\models\ProjectRoleSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* ProjectRoleController implements the CRUD actions for ProjectRole model.
*/
class ProjectRoleController extends Controller
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all ProjectRole models.
* @return mixed
*/
public function actionIndex()
{
$searchModel = new ProjectRoleSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single ProjectRole model.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new ProjectRole model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$model = new ProjectRole();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing ProjectRole model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
/**
* Deletes an existing ProjectRole model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param integer $id
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the ProjectRole model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return ProjectRole the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = ProjectRole::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace backend\modules\project\models;
class ProjectRole extends \common\models\ProjectRole
{
}

View File

@ -0,0 +1,68 @@
<?php
namespace backend\modules\project\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use backend\modules\project\models\ProjectRole;
/**
* ProjectRoleSearch represents the model behind the search form of `backend\modules\project\models\ProjectRole`.
*/
class ProjectRoleSearch extends ProjectRole
{
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['id'], 'integer'],
[['title'], 'safe'],
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = ProjectRole::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
]);
$query->andFilterWhere(['like', 'title', $this->title]);
return $dataProvider;
}
}

View File

@ -4,7 +4,6 @@ namespace backend\modules\project\models;
use yii\base\Model; use yii\base\Model;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;
use backend\modules\project\models\ProjectUser;
/** /**
* ProjectUserSearch represents the model behind the search form of `backend\modules\project\models\ProjectUser`. * ProjectUserSearch represents the model behind the search form of `backend\modules\project\models\ProjectUser`.
@ -17,7 +16,7 @@ class ProjectUserSearch extends ProjectUser
public function rules() public function rules()
{ {
return [ return [
[['id', 'project_id', 'user_id', 'card_id'], 'integer'], [['id', 'project_id', 'user_id', 'card_id', 'project_role_id'], 'integer'],
]; ];
} }
@ -61,6 +60,7 @@ class ProjectUserSearch extends ProjectUser
'project_id' => $this->project_id, 'project_id' => $this->project_id,
'user_id' => $this->user_id, 'user_id' => $this->user_id,
'card_id' => $this->card_id, 'card_id' => $this->card_id,
'project_role_id' => $this->project_role_id,
]); ]);
return $dataProvider; return $dataProvider;

View File

@ -0,0 +1,23 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model backend\modules\project\models\ProjectRole */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="project-role-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>
<div class="form-group">
<?= Html::submitButton('Создать', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@ -0,0 +1,29 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model backend\modules\project\models\ProjectRoleSearch */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="project-role-search">
<?php $form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
]); ?>
<?= $form->field($model, 'id') ?>
<?= $form->field($model, 'title') ?>
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@ -0,0 +1,18 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model backend\modules\project\models\ProjectRole */
$this->title = 'Создать новую роль';
$this->params['breadcrumbs'][] = ['label' => 'Роли сотрудников на проекте ', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="project-role-create">
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@ -0,0 +1,30 @@
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* @var $this yii\web\View */
/* @var $searchModel backend\modules\project\models\ProjectRoleSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Роли сотрудников на проекте';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="project-role-index">
<p>
<?= Html::a('Создать роль', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'title',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>

View File

@ -0,0 +1,21 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model backend\modules\project\models\ProjectRole */
$this->title = 'Update Project Role: ' . $model->title;
$this->params['breadcrumbs'][] = ['label' => 'Project Roles', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->title, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="project-role-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

View File

@ -0,0 +1,36 @@
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
/* @var $this yii\web\View */
/* @var $model backend\modules\project\models\ProjectRole */
$this->title = $model->title;
$this->params['breadcrumbs'][] = ['label' => 'Роли сотрудников на проекте', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
\yii\web\YiiAsset::register($this);
?>
<div class="project-role-view">
<p>
<?= Html::a('Список', ['index', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Изменить', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Удалить', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
</p>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'title',
],
]) ?>
</div>

View File

@ -2,7 +2,8 @@
use backend\modules\card\models\UserCard; use backend\modules\card\models\UserCard;
use backend\modules\project\models\Project; use backend\modules\project\models\Project;
use common\models\User; use backend\modules\project\models\ProjectRole;
use backend\modules\project\models\ProjectUser;
use kartik\select2\Select2; use kartik\select2\Select2;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
@ -37,6 +38,23 @@ use yii\widgets\ActiveForm;
] ]
) ?> ) ?>
<?= $form->field($model, 'project_role_id')->widget(Select2::className(),
[
'data' => ProjectRole::find()->select(['title', 'id'])->indexBy('id')->column(),
'options' => ['placeholder' => '...','class' => 'form-control'],
'pluginOptions' => [
'allowClear' => true,
'multiple' => false,
],
]
) ?>
<?= $form->field($model, 'status')->dropDownList(ProjectUser::statusList(),
[
'prompt' => 'Выберите'
]
) ?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?> <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
</div> </div>

View File

@ -2,6 +2,7 @@
use backend\modules\card\models\UserCard; use backend\modules\card\models\UserCard;
use backend\modules\project\models\Project; use backend\modules\project\models\Project;
use backend\modules\project\models\ProjectRole;
use common\models\User; use common\models\User;
use kartik\select2\Select2; use kartik\select2\Select2;
use yii\helpers\Html; use yii\helpers\Html;
@ -79,6 +80,23 @@ $this->params['breadcrumbs'][] = $this->title;
], ],
]) ])
], ],
[
'attribute' => 'project_role_id',
'value' => 'projectRole.title',
'filter' => Select2::widget([
'model' => $searchModel,
'attribute' => 'project_role_id',
'data' => ProjectRole::find()->select(['title', 'id'])->indexBy('id')->column(),
'pluginOptions' => [
'allowClear' => true,
'width' => '250px',
],
'options' => [
'class' => 'form-control',
'placeholder' => 'Выберите значение'
],
])
],
['class' => 'yii\grid\ActionColumn'], ['class' => 'yii\grid\ActionColumn'],
], ],

View File

@ -43,6 +43,14 @@ YiiAsset::register($this);
'attribute' => 'card_id', 'attribute' => 'card_id',
'value' => ArrayHelper::getValue($model, 'card.fio' ), 'value' => ArrayHelper::getValue($model, 'card.fio' ),
], ],
[
'attribute' => 'project_role_id',
'value' => ArrayHelper::getValue($model, 'projectRole.title' ),
],
[
'attribute' => 'status',
'value' => ArrayHelper::getValue($model->statusList(),$model->status ),
],
], ],
]) ?> ]) ?>

View File

@ -46,6 +46,8 @@ use yii\widgets\ActiveForm;
] ]
]) ?> ]) ?>
<?= $form->field($model, 'description')->textInput(['maxlength' => true]) ?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton('Создать', ['class' => 'btn btn-success']) ?> <?= Html::submitButton('Создать', ['class' => 'btn btn-success']) ?>
</div> </div>

View File

@ -49,6 +49,7 @@ $this->params['breadcrumbs'][] = $this->title;
return TimeHelper::limitTime($model->time_limit); return TimeHelper::limitTime($model->time_limit);
} }
], ],
'description',
['class' => 'yii\grid\ActionColumn'], ['class' => 'yii\grid\ActionColumn'],
], ],
]); ?> ]); ?>

View File

@ -54,6 +54,7 @@ YiiAsset::register($this);
'format' => 'raw', 'format' => 'raw',
'value' => TimeHelper::limitTime($model->time_limit), 'value' => TimeHelper::limitTime($model->time_limit),
], ],
'description',
], ],
]) ?> ]) ?>

View File

@ -1,9 +1,8 @@
<?php <?php
use kartik\date\DatePicker; use kartik\date\DatePicker;
use kartik\datetime\DateTimePicker;
use Symfony\Component\Console\Input\Input;
use unclead\multipleinput\MultipleInput; use unclead\multipleinput\MultipleInput;
use yii\helpers\ArrayHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
@ -70,7 +69,17 @@ $this->registerCss('.list-cell__task{width:73%}')
<?= $form->field($model, 'tomorrow')->textarea(['maxlength' => true]) ?> <?= $form->field($model, 'tomorrow')->textarea(['maxlength' => true]) ?>
<?= $form->field($model, 'user_card_id')->dropDownList( <?= $form->field($model, 'user_card_id')->dropDownList(
\yii\helpers\ArrayHelper::map(common\models\UserCard::find()->all(), 'id', 'fio'), ArrayHelper::map(common\models\UserCard::find()->all(), 'id', 'fio'),
['prompt' => '...']
) ?>
<?= $form->field($model, 'project_id')->dropDownList(
ArrayHelper::map(common\models\Project::find()->all(), 'id', 'name'),
['prompt' => '...']
) ?>
<?= $form->field($model, 'company_id')->dropDownList(
ArrayHelper::map(common\models\Company::find()->all(), 'id', 'name'),
['prompt' => '...'] ['prompt' => '...']
) ?> ) ?>

View File

@ -2,14 +2,12 @@
namespace backend\modules\task\controllers; namespace backend\modules\task\controllers;
use backend\modules\project\models\ProjectUser; use common\models\forms\TasksImportForm;
use backend\modules\task\models\ProjectTaskUser; use common\services\ImportProjectTaskService;
use common\classes\Debug;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;
use yii\web\Response;
use Yii; use Yii;
use backend\modules\task\models\ProjectTask; use backend\modules\task\models\ProjectTask;
use backend\modules\task\models\TaskSearch; use backend\modules\task\models\ProjectTaskSearch;
use yii\web\Controller; use yii\web\Controller;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter; use yii\filters\VerbFilter;
@ -43,7 +41,7 @@ class TaskController extends Controller
*/ */
public function actionIndex() public function actionIndex()
{ {
$searchModel = new TaskSearch(); $searchModel = new ProjectTaskSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams); $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [ return $this->render('index', [
@ -141,4 +139,33 @@ class TaskController extends Controller
throw new NotFoundHttpException('The requested page does not exist.'); throw new NotFoundHttpException('The requested page does not exist.');
} }
public function actionImport()
{
$model = new TasksImportForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$importTaskService = new ImportProjectTaskService();
$query = ProjectTask::genQueryToImport(
(int)$model->companyId,
(int)$model->userId,
(int)$model->projectId,
(int)$model->fromDate,
(int)$model->toDate
);
$tasks = $query->all();
if (!$tasks) {
Yii::$app->session->setFlash('danger', 'Задачи не найдены!');
return Yii::$app->getResponse()->redirect(['/task/task/import']);
} else {
return $importTaskService->importTasks($tasks);
}
}
return $this->render('_form-import', [
'model' => $model,
]);
}
} }

View File

@ -2,15 +2,13 @@
namespace backend\modules\task\models; namespace backend\modules\task\models;
use backend\modules\project\models\ProjectUser;
use yii\base\Model; use yii\base\Model;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;
use backend\modules\task\models\ProjectTask;
/** /**
* TaskSearch represents the model behind the search form of `backend\modules\task\models\Task`. * TaskSearch represents the model behind the search form of `backend\modules\task\models\Task`.
*/ */
class TaskSearch extends ProjectTask class ProjectTaskSearch extends ProjectTask
{ {
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -60,14 +58,15 @@ class TaskSearch extends ProjectTask
// grid filtering conditions // grid filtering conditions
$query->andFilterWhere([ $query->andFilterWhere([
'id' => $this->id, 'id' => $this->id,
'task.project_id' => $this->project_id, 'project_task.project_id' => $this->project_id,
'task.status' => $this->status, 'project_task.status' => $this->status,
'task.created_at' => $this->created_at, 'project_task.execution_priority' => $this->execution_priority,
'task.updated_at' => $this->updated_at, 'project_task.created_at' => $this->created_at,
'project_task.updated_at' => $this->updated_at,
]); ]);
$query->andFilterWhere(['like', 'title', $this->title]) $query->andFilterWhere(['like', 'title', $this->title])
->andFilterWhere(['like', 'task.description', $this->description]); ->andFilterWhere(['like', 'project_task.description', $this->description]);
return $dataProvider; return $dataProvider;
} }

View File

@ -0,0 +1,79 @@
<?php
use backend\modules\project\models\Project;
use common\models\forms\TasksImportForm;
use kartik\date\DatePicker;
use kartik\select2\Select2;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model TasksImportForm*/
/* @var $form yii\widgets\ActiveForm */
$this->title = 'Импорт задач';
$this->params['breadcrumbs'][] = ['label' => 'Tasks', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="task-index">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'companyId')->dropDownList(\common\models\Company::find()
->select(['name', 'id'])->indexBy('id')->column(),
[
'prompt' => 'Выберите'
]
);
?>
<?= $form->field($model, 'userId')->widget(
Select2::class,
[
'data' => \common\models\UserCard::getListUserWithUserId(),
'options' => ['placeholder' => '...', 'class' => 'form-control'],
'pluginOptions' => [
'allowClear' => true
],
]
); ?>
<?= $form->field($model, 'projectId')->widget(
Select2::class,
[
'data' => Project::find()->select(['name', 'id'])->indexBy('id')->column(),
'options' => ['placeholder' => '...', 'class' => 'form-control'],
'pluginOptions' => [
'allowClear' => true
],
]
); ?>
<?= $form->field($model, 'fromDate')->widget(DatePicker::class,[
'type' => DatePicker::TYPE_COMPONENT_APPEND,
'pluginOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);
?>
<?= $form->field($model, 'toDate')->widget(DatePicker::class,[
'type' => DatePicker::TYPE_COMPONENT_APPEND,
'pluginOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);
?>
<div class="form-group">
<?= Html::submitButton('Импорт', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@ -2,6 +2,7 @@
use backend\modules\card\models\UserCard; use backend\modules\card\models\UserCard;
use backend\modules\project\models\Project; use backend\modules\project\models\Project;
use backend\modules\task\models\ProjectTask;
use common\helpers\StatusHelper; use common\helpers\StatusHelper;
use kartik\select2\Select2; use kartik\select2\Select2;
use yii\helpers\Html; use yii\helpers\Html;
@ -59,6 +60,13 @@ use yii\widgets\ActiveForm;
<?= $form->field($model, 'priority')->input('number') ?> <?= $form->field($model, 'priority')->input('number') ?>
<?= $form->field($model, 'execution_priority')->dropDownList(
ProjectTask::priorityList(),
[
'prompt' => 'Выберите'
]
) ?>
<div class="form-group"> <div class="form-group">
<?= Html::submitButton('Создать', ['class' => 'btn btn-success']) ?> <?= Html::submitButton('Создать', ['class' => 'btn btn-success']) ?>
</div> </div>

View File

@ -4,7 +4,7 @@ use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $model backend\modules\task\models\TaskSearch */ /* @var $model backend\modules\task\models\ProjectTaskSearch */
/* @var $form yii\widgets\ActiveForm */ /* @var $form yii\widgets\ActiveForm */
?> ?>

View File

@ -12,7 +12,7 @@ use yii\helpers\Html;
use yii\grid\GridView; use yii\grid\GridView;
/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $searchModel backend\modules\task\models\TaskSearch */ /* @var $searchModel backend\modules\task\models\ProjectTaskSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */ /* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Задачи'; $this->title = 'Задачи';
@ -22,6 +22,7 @@ $this->params['breadcrumbs'][] = $this->title;
<p> <p>
<?= Html::a('Создать задачу', ['create'], ['class' => 'btn btn-success']) ?> <?= Html::a('Создать задачу', ['create'], ['class' => 'btn btn-success']) ?>
<?= Html::a('Импорт задач', ['import'], ['class' => 'btn btn-primary']) ?>
</p> </p>
<?= GridView::widget([ <?= GridView::widget([
@ -58,6 +59,14 @@ $this->params['breadcrumbs'][] = $this->title;
return StatusHelper::statusLabel($model->status); return StatusHelper::statusLabel($model->status);
} }
], ],
[
'attribute' => 'execution_priority',
'format' => 'raw',
'filter' => ProjectTask::priorityList(),
'value' => function($model){
return ProjectTask::getPriority($model->status);
}
],
[ [
'attribute' => 'created_at', 'attribute' => 'created_at',
'format' => ['datetime', 'php:d.m.Y H:i'] 'format' => ['datetime', 'php:d.m.Y H:i']

View File

@ -1,5 +1,6 @@
<?php <?php
use backend\modules\task\models\ProjectTask;
use common\helpers\StatusHelper; use common\helpers\StatusHelper;
use kartik\grid\GridView; use kartik\grid\GridView;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
@ -60,6 +61,12 @@ YiiAsset::register($this);
], ],
'description', 'description',
'priority', 'priority',
[
'attribute' => 'execution_priority',
'value' => function($model){
return ProjectTask::getPriority($model->status);
}
],
], ],
]) ?> ]) ?>
@ -76,7 +83,7 @@ YiiAsset::register($this);
[ [
'attribute' => 'project_user_id', 'attribute' => 'project_user_id',
'value' => 'user.email' 'value' => 'user.username'
], ],
[ [

View File

@ -18,7 +18,8 @@
$projectItems[] = ['label' => $status, 'icon' => 'user', 'url' => ['/project/project?ProjectSearch[status]=' . $key, 'active' => \Yii::$app->controller->id == 'project']]; $projectItems[] = ['label' => $status, 'icon' => 'user', 'url' => ['/project/project?ProjectSearch[status]=' . $key, 'active' => \Yii::$app->controller->id == 'project']];
} }
$projectItems[] = ['label' => 'Сотрудники на проектах', 'icon' => 'users', 'url' => ['/project/project-user'], 'active' => \Yii::$app->controller->id == 'project-user']; $projectItems[] = ['label' => 'Сотрудники на проектах', 'icon' => 'users', 'url' => ['/project/project-user'], 'active' => \Yii::$app->controller->id == 'project-user'];
$projectItems[] = ['label' => 'метки проектов', 'icon' => 'tags', 'url' => ['/project/project-mark'], 'active' => \Yii::$app->controller->id == 'project-mark']; $projectItems[] = ['label' => 'Метки проектов', 'icon' => 'tags', 'url' => ['/project/project-mark'], 'active' => \Yii::$app->controller->id == 'project-mark'];
$projectItems[] = ['label' => 'Роли на проекте', 'icon' => 'user-o', 'url' => ['/project/project-role'], 'active' => \Yii::$app->controller->id == 'project-role'];
?> ?>
<?= dmstr\widgets\Menu::widget( <?= dmstr\widgets\Menu::widget(

View File

@ -1,6 +1,11 @@
<?php <?php
return [ return [
'adminEmail' => 'admin@example.com', 'adminEmail' => 'chancellery@itguild.info',
'supportEmail' => 'support@example.com', 'supportEmail' => 'chancellery@itguild.info',
'senderEmail' => 'chancellery@itguild.info',
'senderName' => 'Chancellery ITguild mailer',
'user.passwordResetTokenExpire' => 3600, 'user.passwordResetTokenExpire' => 3600,
'user.passwordMinLength' => 8,
'tgBotTokenLength' => 6,
'tgBotTokenValidityTime' => 180,
]; ];

View File

@ -23,6 +23,15 @@ class UserQuestionnaireStatusHelper
]; ];
} }
public static function listCompleteStatuses(): array
{
return [
self::STATUS_COMPLETED,
self::STATUS_ON_INSPECTION
];
}
/** /**
* @throws Exception * @throws Exception
*/ */

View File

@ -3,13 +3,11 @@ use yii\helpers\Html;
/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $user common\models\User */ /* @var $user common\models\User */
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
?> ?>
<div class="password-reset"> <div class="password-reset">
<p>Hello <?= Html::encode($user->username) ?>,</p> <p>Hello <?= Html::encode($user->username) ?>,</p>
<p>Follow the link below to reset your password:</p> <p>Your reset token:</p>
<p><?= Html::a(Html::encode($resetLink), $resetLink) ?></p> <p><?= $user->password_reset_token ?></p>
</div> </div>

View File

@ -0,0 +1,10 @@
<?php
/* @var $this yii\web\View */
/* @var $user common\models\User */
?>
Hello <?= $user->username ?>,
You have successfully registered!

View File

@ -0,0 +1,10 @@
<?php
/* @var $this yii\web\View */
/* @var $user common\models\User */
?>
Hello <?= $user->username ?>,
You have successfully registered!

View File

@ -89,11 +89,6 @@ class Answer extends \yii\db\ActiveRecord
->viaTable('question', ['id' => 'question_id']); ->viaTable('question', ['id' => 'question_id']);
} }
// public function getUserQuestionnaire()
// {
// return $this->hasOne(\backend\modules\questionnaire\models\UserQuestionnaire::className(), ['id'])
// }
static function numCorrectAnswers($question_id) static function numCorrectAnswers($question_id)
{ {
return Answer::find() return Answer::find()

View File

@ -11,6 +11,8 @@ use Yii;
* @property int $mark_id * @property int $mark_id
* @property int $entity_type * @property int $entity_type
* @property int $entity_id * @property int $entity_id
*
* @property Mark $mark
*/ */
class MarkEntity extends \yii\db\ActiveRecord class MarkEntity extends \yii\db\ActiveRecord
{ {

View File

@ -2,9 +2,8 @@
namespace common\models; namespace common\models;
use common\classes\Debug;
use Yii;
use yii\behaviors\TimestampBehavior; use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery;
use yii\db\Expression; use yii\db\Expression;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
@ -23,9 +22,11 @@ use yii\helpers\ArrayHelper;
* *
* @property FieldsValue[] $fieldsValues * @property FieldsValue[] $fieldsValues
* @property Company $company * @property Company $company
* @property User $owner
* @property ProjectUser[] $projectUsers * @property ProjectUser[] $projectUsers
* @property Mark[] $mark * @property Mark[] $mark
* @property MarkEntity[] $markEntity * @property MarkEntity[] $markEntity
* @property ProjectTask[] $projectTask
*/ */
class Project extends \yii\db\ActiveRecord class Project extends \yii\db\ActiveRecord
{ {
@ -55,8 +56,8 @@ class Project extends \yii\db\ActiveRecord
public function rules() public function rules()
{ {
return [ return [
['name', 'unique'], [['name', 'owner_id', 'status'], 'required'],
[['name', 'status'], 'required'], [['owner_id', 'name'], 'unique', 'targetAttribute' => ['owner_id', 'name']],
[['description'], 'string'], [['description'], 'string'],
[['created_at', 'updated_at'], 'safe'], [['created_at', 'updated_at'], 'safe'],
[['status'], 'exist', 'skipOnError' => true, 'targetClass' => Status::class, 'targetAttribute' => ['status' => 'id']], [['status'], 'exist', 'skipOnError' => true, 'targetClass' => Status::class, 'targetAttribute' => ['status' => 'id']],
@ -88,7 +89,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getFieldsValues() public function getFieldsValues()
{ {
@ -96,7 +97,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getCompany() public function getCompany()
{ {
@ -104,7 +105,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getColumns() public function getColumns()
{ {
@ -114,7 +115,15 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/
public function getProjectTask(): ActiveQuery
{
return $this->hasMany(ProjectTask::class, ['project_id' => 'id']);
}
/**
* @return ActiveQuery
*/ */
public function getOwner() public function getOwner()
{ {
@ -122,7 +131,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getHh() public function getHh()
{ {
@ -130,7 +139,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getProjectUsers() public function getProjectUsers()
{ {
@ -138,7 +147,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getMark() public function getMark()
{ {
@ -147,7 +156,7 @@ class Project extends \yii\db\ActiveRecord
} }
/** /**
* @return \yii\db\ActiveQuery * @return ActiveQuery
*/ */
public function getMarkEntity() public function getMarkEntity()
{ {

View File

@ -65,6 +65,7 @@ class ProjectColumn extends \yii\db\ActiveRecord
return [ return [
[['title', 'project_id'], 'required'], [['title', 'project_id'], 'required'],
[['project_id', 'status', 'priority'], 'integer'], [['project_id', 'status', 'priority'], 'integer'],
['title', 'unique', 'targetAttribute' => ['title','project_id' => 'status']],
[['created_at', 'updated_at'], 'safe'], [['created_at', 'updated_at'], 'safe'],
[['title'], 'string', 'max' => 255], [['title'], 'string', 'max' => 255],
[['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::className(), 'targetAttribute' => ['project_id' => 'id']], [['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::className(), 'targetAttribute' => ['project_id' => 'id']],

View File

@ -0,0 +1,53 @@
<?php
namespace common\models;
use Yii;
/**
* This is the model class for table "project_role".
*
* @property int $id
* @property string $title
*
* @property ProjectUser[] $projectUsers
*/
class ProjectRole extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'project_role';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['title'], 'string', 'max' => 255],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'title' => 'Название роли',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getProjectUsers()
{
return $this->hasMany(ProjectUser::className(), ['project_role_id' => 'id']);
}
}

View File

@ -21,6 +21,7 @@ use yii\helpers\ArrayHelper;
* @property int $user_id * @property int $user_id
* @property int $executor_id * @property int $executor_id
* @property int $priority * @property int $priority
* @property int $execution_priority
* @property string $description * @property string $description
* @property string $dead_line * @property string $dead_line
* *
@ -28,14 +29,55 @@ use yii\helpers\ArrayHelper;
* @property User $user * @property User $user
* @property UserCard $card * @property UserCard $card
* @property UserCard $cardIdCreator * @property UserCard $cardIdCreator
* @property Company $company
* @property ProjectColumn $column
* @property User $executor
* @property Mark[] $mark * @property Mark[] $mark
* @property MarkEntity[] $markEntity * @property MarkEntity[] $markEntity
* @property ProjectTaskUser[] $taskUsers * @property ProjectTaskUser[] $taskUsers
*/ */
class ProjectTask extends ActiveRecord class ProjectTask extends ActiveRecord
{ {
const STATUS_ACTIVE = 1;
const STATUS_DISABLE = 0; const STATUS_DISABLE = 0;
const STATUS_ACTIVE = 1;
const STATUS_ARCHIVE = 2;
const STATUS_AT_WORK = 3;
const PRIORITY_LOW = 0;
const PRIORITY_MEDIUM = 1;
const PRIORITY_HIGH = 2;
const DAY_IN_UNIX_TIME = 86340; // 23:59:59
/**
* @return string[]
*/
public static function priorityList() :array
{
return [
self::PRIORITY_LOW => 'Низкий',
self::PRIORITY_MEDIUM => 'Средний',
self::PRIORITY_HIGH => 'Высокий',
];
}
/**
* @return int[]
*/
public static function openTaskStatusList(): array
{
return [self::STATUS_ACTIVE, self::STATUS_AT_WORK];
}
/**
* @param $priority
* @return string
* @throws \Exception
*/
public static function getPriority($priority): string
{
return ArrayHelper::getValue(self::priorityList(), $priority);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -64,10 +106,12 @@ class ProjectTask extends ActiveRecord
{ {
return [ return [
[['project_id', 'status', 'title', 'description',], 'required'], [['project_id', 'status', 'title', 'description',], 'required'],
[['project_id', 'status', 'column_id', 'user_id', 'executor_id', 'priority'], 'integer'], [['project_id', 'status', 'column_id', 'user_id', 'executor_id', 'priority', 'execution_priority'], 'integer'],
[['created_at', 'updated_at', 'dead_line'], 'safe'], [['created_at', 'updated_at', 'dead_line'], 'safe'],
['execution_priority', 'in', 'range' => [self::PRIORITY_LOW, self::PRIORITY_MEDIUM, self::PRIORITY_HIGH]],
['title', 'unique', 'targetAttribute' => ['title', 'project_id'], 'message' => 'Такая задача уже создана'], ['title', 'unique', 'targetAttribute' => ['title', 'project_id'], 'message' => 'Такая задача уже создана'],
[['title'], 'string', 'max' => 255], [['title'], 'string', 'max' => 255],
['status', 'in', 'range' => [self::STATUS_DISABLE, self::STATUS_ACTIVE, self::STATUS_ARCHIVE, self::STATUS_AT_WORK]],
[['description'], 'string', 'max' => 1500], [['description'], 'string', 'max' => 1500],
[['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::className(), 'targetAttribute' => ['project_id' => 'id']], [['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::className(), 'targetAttribute' => ['project_id' => 'id']],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
@ -94,6 +138,77 @@ class ProjectTask extends ActiveRecord
'executor_id' => 'Исполнитель', 'executor_id' => 'Исполнитель',
'priority' => 'Приоритет', 'priority' => 'Приоритет',
'dead_line' => 'Срок выполнения задачи', 'dead_line' => 'Срок выполнения задачи',
'execution_priority' => 'Приоритет выполнения',
];
}
/**
* @return string[]
*/
public function fields(): array
{
return [
'id',
'project_id',
'project_name' => function () {
return $this->project->name ?? null;
},
'title',
'created_at',
'updated_at',
'dead_line',
'description',
'status',
'column_id',
'user_id',
'user' => function () {
return [
"fio" => $this->user->userCard->fio ?? ($this->user->id ?? ''),
"avatar" => $this->user->userCard->photo ?? '',
];
},
'executor_id',
'priority',
'executor' => function () {
if ($this->executor) {
return [
"fio" => $this->executor->userCard->fio ?? $this->executor->username,
"avatar" => $this->executor->userCard->photo ?? '',
];
}
return null;
},
'comment_count' => function () {
return $this->getCommentCount();
},
'taskUsers',
'mark',
'execution_priority'
];
}
/**
* @return bool|int|string|null
*/
public function getCommentCount()
{
return Comment::find()->where(['entity_id' => $this->id, 'entity_type' => 2, 'status' => Comment::STATUS_ACTIVE])->count();
}
/**
* @return string[]
*/
public function extraFields(): array
{
return [
'timers',
'column' => function () {
return [
'column_title' => $this->column->title ?? null
];
},
'mark'
]; ];
} }
@ -124,6 +239,15 @@ class ProjectTask extends ActiveRecord
return $this->hasOne(Project::className(), ['id' => 'project_id']); return $this->hasOne(Project::className(), ['id' => 'project_id']);
} }
/**
* @return ActiveQuery
*/
public function getCompany(): ActiveQuery
{
return $this->hasOne(Company::class,['id' => 'company_id'])
->via('project');
}
/** /**
* @return ActiveQuery * @return ActiveQuery
*/ */
@ -184,4 +308,71 @@ class ProjectTask extends ActiveRecord
return ArrayHelper::map( return ArrayHelper::map(
self::find()->joinWith(['user', 'project'])->where(['project_id' => $task_id])->all(), 'id', 'user.username'); self::find()->joinWith(['user', 'project'])->where(['project_id' => $task_id])->all(), 'id', 'user.username');
} }
/**
* @return string
*/
public function getTaskUsersToStr(): string
{
$participants = '';
foreach ($this->taskUsers as $taskUser) {
$participants .= $taskUser->user->userCard->fio ?? $taskUser->user->username;
$participants .= ', ';
}
return $participants;
}
/**
* @return string
*/
public function getMarkTitleToStr(): string
{
$tags = '';
foreach ($this->markEntity as $markEntity) {
$tags .= $markEntity->mark->title . ', ';
}
return $tags;
}
/**
* @param int|null $companyId
* @param int|null $userId
* @param int|null $projectId
* @param int|null $fromDate
* @param int|null $toDate
* @return ActiveQuery
*/
public static function genQueryToImport(
int $companyId = null,
int $userId = null,
int $projectId = null,
int $fromDate = null,
int $toDate = null
): ActiveQuery
{
$query = ProjectTask::find();
if ($companyId) {
$query->joinWith('company')
->andWhere(['company.id' => $companyId]);
}
if ($userId) {
$query->andWhere(['project_task.user_id' => $userId]);
}
if ($projectId) {
$query->andWhere(['project_task.project_id' => $projectId]);
}
if ($fromDate) {
$query->andFilterWhere(['>=', 'project_task.created_at', date("Y-m-d H:i:s", $fromDate)]);
}
if ($toDate) {
$query->andFilterWhere(['<=', 'project_task.created_at', date("Y-m-d H:i:s", ($toDate + self::DAY_IN_UNIX_TIME))]);
}
return $query;
}
} }

View File

@ -11,8 +11,8 @@ use yii\db\ActiveQuery;
* @property int $task_id * @property int $task_id
* @property int $user_id * @property int $user_id
* *
* @property ProjectUser $projectUser
* @property ProjectTask $task * @property ProjectTask $task
* @property User $user
*/ */
class ProjectTaskUser extends \yii\db\ActiveRecord class ProjectTaskUser extends \yii\db\ActiveRecord
{ {

View File

@ -14,14 +14,28 @@ use yii\helpers\ArrayHelper;
* @property int $card_id * @property int $card_id
* @property int $project_id * @property int $project_id
* @property int $user_id * @property int $user_id
* @property int $project_role_id
* @property int $status
* *
* @property Project $project * @property Project $project
* @property UserCard $card * @property UserCard $card
* @property User $user * @property User $user
* @property ProjectRole $projectRole
* @property ProjectTaskUser[] $taskUsers * @property ProjectTaskUser[] $taskUsers
*/ */
class ProjectUser extends \yii\db\ActiveRecord class ProjectUser extends \yii\db\ActiveRecord
{ {
public const STATUS_INACTIVE = 0;
public const STATUS_ACTIVE = 1;
public static function statusList() :array
{
return [
self::STATUS_INACTIVE => 'Не активен',
self::STATUS_ACTIVE => 'Активен',
];
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -39,10 +53,13 @@ class ProjectUser extends \yii\db\ActiveRecord
[['user_id', 'project_id', 'card_id'], 'required'], [['user_id', 'project_id', 'card_id'], 'required'],
['user_id', 'unique', 'targetAttribute' => ['user_id', 'project_id'], 'message'=>'Сотрудник уже назначен на этот проект'], ['user_id', 'unique', 'targetAttribute' => ['user_id', 'project_id'], 'message'=>'Сотрудник уже назначен на этот проект'],
['card_id', 'unique', 'targetAttribute' => ['card_id', 'project_id'], 'message'=>'Сотрудник уже назначен на этот проект'], ['card_id', 'unique', 'targetAttribute' => ['card_id', 'project_id'], 'message'=>'Сотрудник уже назначен на этот проект'],
[['card_id', 'project_id', 'user_id'], 'integer'], [['card_id', 'project_id', 'user_id', 'project_role_id', 'status'], 'integer'],
[['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::className(), 'targetAttribute' => ['project_id' => 'id']], [['status'], 'default', 'value'=> self::STATUS_ACTIVE],
[['card_id'], 'exist', 'skipOnError' => true, 'targetClass' => UserCard::className(), 'targetAttribute' => ['card_id' => 'id']], ['status', 'in', 'range' => [self::STATUS_INACTIVE, self::STATUS_ACTIVE]],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], [['project_id'], 'exist', 'skipOnError' => true, 'targetClass' => Project::class, 'targetAttribute' => ['project_id' => 'id']],
[['card_id'], 'exist', 'skipOnError' => true, 'targetClass' => UserCard::class, 'targetAttribute' => ['card_id' => 'id']],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::class, 'targetAttribute' => ['user_id' => 'id']],
[['project_role_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProjectRole::class, 'targetAttribute' => ['project_role_id' => 'id']],
]; ];
} }
@ -56,6 +73,8 @@ class ProjectUser extends \yii\db\ActiveRecord
'card_id' => 'Карточка', 'card_id' => 'Карточка',
'project_id' => 'Проект', 'project_id' => 'Проект',
'user_id' => 'Сотрудник', 'user_id' => 'Сотрудник',
'project_role_id' => 'Роль на проекте',
'status' => 'Статус'
]; ];
} }
@ -64,7 +83,7 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getProject() public function getProject()
{ {
return $this->hasOne(Project::className(), ['id' => 'project_id']); return $this->hasOne(Project::class, ['id' => 'project_id']);
} }
/** /**
@ -72,7 +91,7 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getCard() public function getCard()
{ {
return $this->hasOne(UserCard::className(), ['id' => 'card_id']); return $this->hasOne(UserCard::class, ['id' => 'card_id']);
} }
/** /**
@ -80,7 +99,7 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getUser() public function getUser()
{ {
return $this->hasOne(User::className(), ['id' => 'user_id']); return $this->hasOne(User::class, ['id' => 'user_id']);
} }
/** /**
@ -88,7 +107,7 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getTasks() public function getTasks()
{ {
return $this->hasMany(ProjectTask::className(), ['project_user_id' => 'id']); return $this->hasMany(ProjectTask::class, ['project_user_id' => 'id']);
} }
/** /**
@ -96,7 +115,15 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getTasksByProject() public function getTasksByProject()
{ {
return $this->hasMany(ProjectTask::className(), ['project_id' => 'project_id']); return $this->hasMany(ProjectTask::class, ['project_id' => 'project_id']);
}
/**
* @return ActiveQuery
*/
public function getProjectRole(): ActiveQuery
{
return $this->hasOne(ProjectRole::class, ['id' => 'project_role_id']);
} }
/** /**
@ -104,7 +131,7 @@ class ProjectUser extends \yii\db\ActiveRecord
*/ */
public function getTaskUsers() public function getTaskUsers()
{ {
return $this->hasMany(ProjectTaskUser::className(), ['project_user_id' => 'id']); return $this->hasMany(ProjectTaskUser::class, ['project_user_id' => 'id']);
} }
public static function usersByProjectArr($project_id): array public static function usersByProjectArr($project_id): array

View File

@ -133,7 +133,6 @@ class Question extends \yii\db\ActiveRecord
{ {
return self::find()->where(['questionnaire_id' => $questionnaire_id]) return self::find()->where(['questionnaire_id' => $questionnaire_id])
->andWhere(['status' => '1']) ->andWhere(['status' => '1'])
->AsArray()
->all(); ->all();
} }
} }

View File

@ -15,6 +15,7 @@ use yii\helpers\ArrayHelper;
* @property int $category_id * @property int $category_id
* @property string $title * @property string $title
* @property int $status * @property int $status
* @property string $description
* @property string $created_at * @property string $created_at
* @property string $updated_at * @property string $updated_at
* @property string $time_limit * @property string $time_limit
@ -55,7 +56,7 @@ class Questionnaire extends ActiveRecord
[['category_id', 'status'], 'integer'], [['category_id', 'status'], 'integer'],
[['created_at', 'updated_at', 'time_limit'], 'safe'], [['created_at', 'updated_at', 'time_limit'], 'safe'],
['title', 'unique'], ['title', 'unique'],
[['title'], 'string', 'max' => 255], [['title', 'description'], 'string', 'max' => 255],
['status', 'default', 'value' => true], ['status', 'default', 'value' => true],
[['category_id'], 'exist', 'skipOnError' => true, 'targetClass' => QuestionnaireCategory::className(), 'targetAttribute' => ['category_id' => 'id']], [['category_id'], 'exist', 'skipOnError' => true, 'targetClass' => QuestionnaireCategory::className(), 'targetAttribute' => ['category_id' => 'id']],
]; ];
@ -70,6 +71,7 @@ class Questionnaire extends ActiveRecord
'id' => 'ID', 'id' => 'ID',
'category_id' => 'Категория', 'category_id' => 'Категория',
'title' => 'Название анкеты', 'title' => 'Название анкеты',
'description' => 'Описание',
'status' => 'Статус', 'status' => 'Статус',
'created_at' => 'Created At', 'created_at' => 'Created At',
'updated_at' => 'Updated At', 'updated_at' => 'Updated At',

View File

@ -14,6 +14,8 @@ use Yii;
* @property string $difficulties * @property string $difficulties
* @property string $tomorrow * @property string $tomorrow
* @property int $user_card_id * @property int $user_card_id
* @property int $project_id
* @property int $company_id
* @property int $status * @property int $status
* *
* @property UserCard $userCard * @property UserCard $userCard
@ -36,11 +38,13 @@ class Reports extends \yii\db\ActiveRecord
public function rules() public function rules()
{ {
return [ return [
[['user_card_id', 'status'], 'integer'], [['user_card_id', 'status', 'company_id', 'project_id'], 'integer'],
[['_task'], 'checkIsArray'], [['_task'], 'checkIsArray'],
[['user_card_id', 'created_at'], 'required'], [['user_card_id', 'created_at'], 'required'],
[['today', 'difficulties', 'tomorrow', 'created_at'], 'string', 'max' => 255], [['today', 'difficulties', 'tomorrow', 'created_at'], 'string', 'max' => 255],
[['user_card_id'], 'exist', 'skipOnError' => true, 'targetClass' => UserCard::className(), 'targetAttribute' => ['user_card_id' => 'id']], [['user_card_id'], 'exist', 'skipOnError' => true, 'targetClass' => UserCard::class, 'targetAttribute' => ['user_card_id' => 'id']],
[['project_id'], 'exist', 'skipOnEmpty' => true, 'targetClass' => Project::class, 'targetAttribute' => ['project_id' => 'id']],
[['company_id'], 'exist', 'skipOnEmpty' => true, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
]; ];
} }
@ -56,7 +60,9 @@ class Reports extends \yii\db\ActiveRecord
'difficulties' => 'Какие сложности возникли?', 'difficulties' => 'Какие сложности возникли?',
'tomorrow' => 'Что планируется сделать завтра?', 'tomorrow' => 'Что планируется сделать завтра?',
'user_card_id' => 'Пользователь', 'user_card_id' => 'Пользователь',
'status' => 'Статус' 'status' => 'Статус',
'project_id' => 'ID проекта',
'company_id' => 'ID компании'
]; ];
} }

View File

@ -2,8 +2,6 @@
namespace common\models; namespace common\models;
use Yii;
/** /**
* This is the model class for table "test_task". * This is the model class for table "test_task".
* *

View File

@ -231,6 +231,6 @@ class User extends ActiveRecord implements IdentityInterface, UserRbacInterface
public function getProjectUser() public function getProjectUser()
{ {
return $this->hasMany(ProjectUser::className(), ['user_id' => 'id']); return $this->hasMany(ProjectUser::class, ['user_id' => 'id']);
} }
} }

View File

@ -2,14 +2,11 @@
namespace common\models; namespace common\models;
use common\classes\Debug;
use Exception; use Exception;
use phpDocumentor\Reflection\Types\This;
use Yii; use Yii;
use yii\behaviors\TimestampBehavior; use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery; use yii\db\ActiveQuery;
use yii\db\Expression; use yii\db\Expression;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
/** /**
@ -45,6 +42,7 @@ use yii\helpers\ArrayHelper;
* *
* @property FieldsValue[] $fieldsValues * @property FieldsValue[] $fieldsValues
* @property ProjectUser[] $projectUsers * @property ProjectUser[] $projectUsers
* @property CardSkill[] $skillValues
* @property ResumeTemplate $resumeTemplate * @property ResumeTemplate $resumeTemplate
* @property Position $position * @property Position $position
* @property Status $status0 * @property Status $status0
@ -246,6 +244,13 @@ class UserCard extends \yii\db\ActiveRecord
return $this->hasMany(CardSkill::class, ['card_id' => 'id'])->with('skill'); return $this->hasMany(CardSkill::class, ['card_id' => 'id'])->with('skill');
} }
public function getSkillsName()
{
return $this->getSkillValues()
->leftJoin('skill', 'card_skill.skill_id = skill.id')
->select('skill.name')->column();
}
public static function getNameSkills() public static function getNameSkills()
{ {
return ArrayHelper::map(Skill::find()->all(), 'id', 'name'); return ArrayHelper::map(Skill::find()->all(), 'id', 'name');

View File

@ -26,6 +26,8 @@ use \backend\modules\questionnaire\models\Answer;
* @property int $score * @property int $score
* @property int $status * @property int $status
* @property double $percent_correct_answers * @property double $percent_correct_answers
* @property string $testing_date
* @property string $start_testing
* *
* @property Questionnaire $questionnaire * @property Questionnaire $questionnaire
* @property User $user * @property User $user
@ -63,7 +65,7 @@ class UserQuestionnaire extends ActiveRecord
[['questionnaire_id', 'user_id', 'status'], 'required'], [['questionnaire_id', 'user_id', 'status'], 'required'],
[['questionnaire_id', 'user_id', 'score', 'status'], 'integer'], [['questionnaire_id', 'user_id', 'score', 'status'], 'integer'],
[['percent_correct_answers'], 'number'], [['percent_correct_answers'], 'number'],
[['created_at', 'updated_at', 'testing_date'], 'safe'], [['created_at', 'updated_at', 'testing_date', 'start_testing'], 'safe'],
[['uuid'], 'string', 'max' => 36], [['uuid'], 'string', 'max' => 36],
[['uuid'], 'unique'], [['uuid'], 'unique'],
[['questionnaire_id'], 'exist', 'skipOnError' => true, 'targetClass' => Questionnaire::className(), 'targetAttribute' => ['questionnaire_id' => 'id']], [['questionnaire_id'], 'exist', 'skipOnError' => true, 'targetClass' => Questionnaire::className(), 'targetAttribute' => ['questionnaire_id' => 'id']],
@ -98,6 +100,7 @@ class UserQuestionnaire extends ActiveRecord
'created_at' => 'Дата создания', 'created_at' => 'Дата создания',
'updated_at' => 'Дата обновления', 'updated_at' => 'Дата обновления',
'testing_date' => 'Дата тестирования', 'testing_date' => 'Дата тестирования',
'start_testing' => 'Дата начала тестирования',
'percent_correct_answers' => 'Процент правильных ответов', 'percent_correct_answers' => 'Процент правильных ответов',
]; ];
} }
@ -179,18 +182,9 @@ class UserQuestionnaire extends ActiveRecord
public static function findActiveUserQuestionnaires($user_id): array public static function findActiveUserQuestionnaires($user_id): array
{ {
$models = self::find() return self::find()
->where(['user_id' => $user_id]) ->where(['user_id' => $user_id])
->andWhere(['not', ['user_questionnaire.status' => 0]]) ->andWhere(['not', ['user_questionnaire.status' => 0]])
->all(); ->all();
$modelsArr = array();
foreach ($models as $model) {
$modelsArr[] = array_merge($model->toArray(), [
'questionnaire_title' => $model->getQuestionnaireTitle()
]);
}
return $modelsArr;
} }
} }

View File

@ -0,0 +1,78 @@
<?php
namespace common\models;
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
/**
* This is the model class for table "user_tg_bot_dialog".
*
* @property int $id
* @property int $user_id
* @property int $dialog_id
* @property string $created_at
* @property string $updated_at
*
* @property User $user
*/
class UserTgBotDialog extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'user_tg_bot_dialog';
}
public function behaviors()
{
return [
[
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => new Expression('NOW()'),
],
];
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['user_id', 'dialog_id'], 'integer'],
[['dialog_id'], 'required'],
[['created_at', 'updated_at'], 'safe'],
[['dialog_id'], 'unique'],
[['user_id'], 'unique'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'user_id' => 'User ID',
'dialog_id' => 'Dialog ID',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
}

View File

@ -0,0 +1,89 @@
<?php
namespace common\models;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery;
use yii\db\Expression;
/**
* This is the model class for table "user_tg_bot_token".
*
* @property int $id
* @property int $user_id
* @property string $token
* @property string $created_at
* @property string $updated_at
* @property string $expired_at
*
* @property User $user
*/
class UserTgBotToken extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'user_tg_bot_token';
}
public function behaviors()
{
return [
[
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => new Expression('NOW()'),
],
];
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['user_id'], 'integer'],
[['token'], 'required'],
[['created_at', 'updated_at', 'expired_at'], 'safe'],
[['token'], 'string', 'max' => 255],
[['token'], 'unique'],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'user_id' => 'User ID',
'token' => 'Token',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'expired_at' => 'Expired At',
];
}
/**
* @return ActiveQuery
*/
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
/**
* @param string $tokenValue
* @return bool
*/
public static function checkExistsByToken(string $tokenValue): bool
{
return self::find()->where(['token' => $tokenValue])->exists();
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace common\models\email;
class Email
{
/**
* @var string
*/
public string $sendTo;
/**
* @var string
*/
public string $subject;
/**
* @var array
*/
public array $mailLayout;
/**
* @var array
*/
public array $params;
}

View File

@ -0,0 +1,20 @@
<?php
namespace common\models\email;
use common\models\User;
use Yii;
class RegistrationEmail extends Email
{
/**
* @param User $user
*/
public function __construct(User $user)
{
$this->sendTo = $user->email;
$this->subject = 'Account registration at ' . Yii::$app->name;
$this->mailLayout = ['html' => 'signup-html', 'text' => 'signup-text'];
$this->params = ['user' => $user];
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace common\models\email;
use common\models\User;
use Yii;
class ResetPasswordEmail extends Email
{
/**
* @param User $user
*/
public function __construct(User $user)
{
$this->sendTo = $user->email;
$this->subject = 'Password reset for ' . Yii::$app->name;
$this->mailLayout = ['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text']; //+
$this->params = ['user' => $user];//+
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace common\models\forms;
use yii\base\Model;
class TasksImportForm extends Model
{
public $companyId;
public $userId;
public $projectId;
public $fromDate;
public $toDate;
/**
* @return array
*/
public function rules()
{
return [
[['companyId', 'userId', 'projectId'], 'integer'],
['fromDate', 'date', 'format' => 'php:Y-m-d', 'timestampAttribute' => 'fromDate'],
['toDate', 'date', 'format' => 'php:Y-m-d', 'timestampAttribute' => 'toDate'],
];
}
public function attributeLabels()
{
return [
'companyId' => 'ID компании',
'userId' => 'ID пользователя',
'projectId' => 'ID проекта',
'fromDate' => 'Дата начала поиска',
'toDate' => 'Дата конца поиска',
];
}
/**
* @return string
*/
public function formName(): string
{
return '';
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace common\services;
use common\models\email\Email;
use Yii;
class EmailService
{
private array $sendFrom;
public function __construct()
{
$this->sendFrom = [Yii::$app->params['senderEmail'] => Yii::$app->name . ' robot'];
}
/**
* @param Email $email
* @return bool
*/
public function sendEmail(Email $email): bool
{
return Yii::$app->mailer->compose(
$email->mailLayout,
$email->params,
)
->setFrom($this->sendFrom)
->setTo($email->sendTo)
->setSubject($email->subject)
->send();
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace common\services;
use common\models\ProjectTask;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use yii\helpers\ArrayHelper;
class ImportProjectTaskService
{
/**
* @param array $tasks
* @return string|void
*/
public function importTasks(array $tasks)
{
try {
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet
->setCellValue('A1', 'ID')
->setCellValue('B1', 'ID проекта')
->setCellValue('C1', 'Название проекта')
->setCellValue('D1', 'Задача')
->setCellValue('E1', 'Дата создания')
->setCellValue('F1', 'Дата обновления')
->setCellValue('G1', 'Дедлайн')
->setCellValue('H1', 'Описание')
->setCellValue('I1', 'Статус')
->setCellValue('J1', 'Колонка')
->setCellValue('G1', 'ID создателя задачи')
->setCellValue('K1', 'Создатель задачи')
->setCellValue('L1', 'ID исполнителя')
->setCellValue('M1', 'Приоритет')
->setCellValue('N1', 'Исполнитель')
->setCellValue('O1', 'Количество коментариев')
->setCellValue('P1', 'Участники')
->setCellValue('Q1', 'Теги')
->setCellValue('R1', 'Приоритет выполнения');
$i = 2;
/** @var ProjectTask $task */
foreach ($tasks as $task) {
$sheet
->setCellValue('A' . $i, $task->id)
->setCellValue('B' . $i, $task->project_id)
->setCellValue('C' . $i, $task->project->name)
->setCellValue('D' . $i, $task->title)
->setCellValue('E' . $i, $task->created_at)
->setCellValue('F' . $i, $task->updated_at)
->setCellValue('G' . $i, $task->dead_line)
->setCellValue('H' . $i, $task->description)
->setCellValue('I' . $i, ArrayHelper::getValue(ProjectTask::getStatus(), $task->status))
->setCellValue('J' . $i, $task->column->title)
->setCellValue('G' . $i, $task->user_id)
->setCellValue('K' . $i, $task->user->userCard->fio ?? ($task->user->username ?? 'kkk'))
->setCellValue('L' . $i, $task->executor_id)
->setCellValue('M' . $i, $task->priority)
->setCellValue('N' . $i, $task->executor->userCard->fio ?? ($task->executor->username ?? 'ggg'))
->setCellValue('O' . $i, $task->getCommentCount())
->setCellValue('P' . $i, $task->getTaskUsersToStr())
->setCellValue('Q' . $i, $task->getMarkTitleToStr())
->setCellValue('R' . $i, $task->execution_priority);
$i++;
}
$writer = new Xlsx($spreadsheet);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="'. urlencode('tasks.xlsx').'"');
$writer->save('php://output');
exit();
} catch (\Exception $ex) {
return $ex->getMessage();
}
}
}

View File

@ -1,57 +0,0 @@
<?php
namespace common\services;
use common\models\ProjectTaskUser;
use frontend\modules\api\models\ProjectTask;
class TaskService
{
public static function createTask($taskParams)
{
$task = new ProjectTask();
$task->load($taskParams, '');
$task->save();
return $task;
}
public static function getTask($task_id): ?ProjectTask
{
return ProjectTask::findOne($task_id);
}
public static function getTaskList($task_id): array
{
return ProjectTask::find()->asArray()->all();
}
public static function getTaskListByProject($project_id): array
{
return ProjectTask::find()->where(['project_id' => $project_id])->orderBy('priority DESC')->all();
}
public static function getTaskListByUser($user_id): array
{
$taskIdList = ProjectTaskUser::find()->where(['user_id' => $user_id])->select('task_id')->column();
return ProjectTask::find()->where([ 'IN', 'id', $taskIdList])->orWhere(['user_id' => $user_id])->orderBy('priority DESC')->all();
}
public static function updateTask($task_params): ?ProjectTask
{
$modelTask = ProjectTask::findOne($task_params['task_id']);
if (isset($task_params['executor_id']) && $task_params['executor_id'] == 0){
$task_params['executor_id'] = null;
}
$modelTask->load($task_params, '');
$modelTask->save();
return $modelTask;
}
public static function taskExists($task_id): bool
{
return ProjectTask::find()->where(['id' => $task_id])->exists();
}
}

View File

@ -1,78 +0,0 @@
<?php
namespace common\services;
use common\models\Question;
use common\models\UserQuestionnaire;
use yii\base\InvalidConfigException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException;
class UserQuestionnaireService
{
public static function getQuestionnaireList($user_id): array
{
$userQuestionnaireModels = UserQuestionnaire::findActiveUserQuestionnaires($user_id);
array_walk($userQuestionnaireModels, function (&$arr) {
unset(
$arr['questionnaire_id'],
$arr['created_at'],
$arr['updated_at'],
$arr['id']
);
});
return $userQuestionnaireModels;
}
/**
* @throws NotFoundHttpException
* @throws InvalidConfigException
*/
public static function calculateScore($user_questionnaire_uuid): UserQuestionnaire
{
$userQuestionnaireModel = UserQuestionnaire::findOne(['uuid' => $user_questionnaire_uuid]);
if (empty($userQuestionnaireModel)) {
throw new NotFoundHttpException('The questionnaire with this uuid does not exist');
}
ScoreCalculatorService::rateResponses($userQuestionnaireModel);
if (ScoreCalculatorService::checkAnswerFlagsForNull($userQuestionnaireModel)) {
ScoreCalculatorService::calculateScore($userQuestionnaireModel);
} else {
$userQuestionnaireModel->status = 3;
$userQuestionnaireModel->save();
}
return $userQuestionnaireModel;
}
/**
* @throws ServerErrorHttpException
*/
public static function getQuestionNumber($user_questionnaire_uuid): array
{
$userQuestionnaireModel = UserQuestionnaire::findOne(['uuid' => $user_questionnaire_uuid]);
if (empty($userQuestionnaireModel)) {
throw new ServerErrorHttpException('Not found UserQuestionnaire');
}
$count = Question::find()
->where(['questionnaire_id' => $userQuestionnaireModel->questionnaire_id])
->andWhere(['status' => 1])
->count();
return array('question_number' => $count);
}
/**
* @throws ServerErrorHttpException
*/
public static function getPointsNumber($user_questionnaire_uuid)
{
$userQuestionnaireModel = UserQuestionnaire::findOne(['uuid' => $user_questionnaire_uuid]);
if (empty($userQuestionnaireModel)) {
throw new ServerErrorHttpException('Not found UserQuestionnaire');
}
$pointSum = Question::find()
->where(['questionnaire_id' => $userQuestionnaireModel->questionnaire_id])
->andWhere(['status' => 1])
->sum('score');
return array('sum_point' => $pointSum);
}
}

View File

@ -37,7 +37,9 @@
"kartik-v/yii2-mpdf": "dev-master", "kartik-v/yii2-mpdf": "dev-master",
"mihaildev/yii2-ckeditor": "*", "mihaildev/yii2-ckeditor": "*",
"developeruz/yii2-db-rbac": "*", "developeruz/yii2-db-rbac": "*",
"zircote/swagger-php": "^4.7" "zircote/swagger-php": "^4.7",
"phpoffice/phpspreadsheet": "^1.29",
"kartik-v/yii2-widget-datepicker": "dev-master"
}, },
"require-dev": { "require-dev": {
"yiisoft/yii2-debug": "~2.0.0", "yiisoft/yii2-debug": "~2.0.0",

View File

@ -1,4 +1,4 @@
<?php <?php
return [ return [
'adminEmail' => 'admin@example.com', 'adminEmail' => 'chancellery@itguild.info',
]; ];

View File

@ -0,0 +1,31 @@
<?php
use yii\db\Migration;
/**
* Class m231013_122324_add_foreign_key_in_project_from_owner_id_to_user_id
*/
class m231013_122324_add_foreign_key_in_project_from_owner_id_to_user_id extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addForeignKey(
'project_user',
'project',
'owner_id',
'user',
'id'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey('project_user', 'project');
}
}

View File

@ -0,0 +1,25 @@
<?php
use yii\db\Migration;
/**
* Handles adding columns to table `{{%project_task}}`.
*/
class m231013_144526_add_execution_priority_column_to_project_task_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('project_task', 'execution_priority', $this->integer(1));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('project_task', 'execution_priority');
}
}

View File

@ -0,0 +1,33 @@
<?php
use yii\db\Migration;
/**
* Class m231023_122338_create_user_tg_bot_token
*/
class m231023_122338_create_user_tg_bot_token extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%user_tg_bot_token}}', [
'id' => $this->primaryKey(),
'user_id' => $this->integer(),
'token' => $this->string()->notNull()->unique(),
'created_at' => $this->dateTime(),
'updated_at' => $this->dateTime(),
'expired_at' => $this->dateTime(),
]);
$this->addForeignKey('user_user_tg_bot_token', 'user_tg_bot_token', 'user_id', 'user', 'id');
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('user_tg_bot_token');
}
}

View File

@ -0,0 +1,32 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%user_tg_bot_dialog}}`.
*/
class m231024_132757_create_user_tg_bot_dialog_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%user_tg_bot_dialog}}', [
'id' => $this->primaryKey(),
'user_id' => $this->integer(),
'dialog_id' => $this->integer()->notNull()->unique(),
'created_at' => $this->dateTime(),
'updated_at' => $this->dateTime(),
]);
$this->addForeignKey('user_user_tg_bot_dialog', 'user_tg_bot_dialog', 'user_id', 'user', 'id');
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('{{%user_tg_bot_dialog}}');
}
}

View File

@ -0,0 +1,25 @@
<?php
use yii\db\Migration;
/**
* Class m231026_071555_add_column_description_to_questionnaire_table
*/
class m231026_071555_add_column_description_to_questionnaire_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('questionnaire', 'description', $this->string(255));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('questionnaire', 'description');
}
}

View File

@ -0,0 +1,34 @@
<?php
use yii\db\Migration;
/**
* Class m231102_113213_add_column_project_id_reports_table
*/
class m231102_113213_add_column_project_id_reports_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('reports', 'project_id', $this->integer()->defaultValue(null));
$this->addForeignKey(
'reports_project_id',
'reports',
'project_id',
'project',
'id'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey('reports_project_id', 'reports');
$this->dropColumn('reports', 'project_id');
}
}

View File

@ -0,0 +1,34 @@
<?php
use yii\db\Migration;
/**
* Class m231102_113324_add_column_company_id_reports_table
*/
class m231102_113324_add_column_company_id_reports_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('reports', 'company_id', $this->integer()->defaultValue(null));
$this->addForeignKey(
'reports_company_id',
'reports',
'company_id',
'project',
'id'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey('reports_company_id', 'reports');
$this->dropColumn('reports', 'company_id');
}
}

View File

@ -0,0 +1,25 @@
<?php
use yii\db\Migration;
/**
* Class m231114_072752_add_column_start_testing_to_user_questionnaire
*/
class m231114_072752_add_column_start_testing_to_user_questionnaire extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('user_questionnaire', 'start_testing', $this->dateTime());
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('user_questionnaire', 'start_testing');
}
}

View File

@ -0,0 +1,28 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `{{%project_role}}`.
*/
class m231120_121208_create_project_role_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('{{%project_role}}', [
'id' => $this->primaryKey(),
'title' => $this->string(),
]);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('{{%project_role}}');
}
}

View File

@ -0,0 +1,38 @@
<?php
use yii\db\Migration;
/**
* Class m231120_122131_add_project_role_id_to_project_user_table
*/
class m231120_122131_add_project_role_id_to_project_user_table extends Migration
{
private const TABLE_NAME = 'project_user';
private const TABLE_COLUMN = 'project_role_id';
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn(self::TABLE_NAME, self::TABLE_COLUMN, $this->integer()->defaultValue(null));
$this->addForeignKey(
'project_role_project_user',
self::TABLE_NAME,
self::TABLE_COLUMN,
'project_role',
'id'
);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey('project_role_project_user', self::TABLE_NAME);
$this->dropColumn(self::TABLE_NAME, self::TABLE_COLUMN );
}
}

View File

@ -0,0 +1,27 @@
<?php
use yii\db\Migration;
/**
* Handles adding columns to table `{{%project_user}}`.
*/
class m231120_134302_add_status_column_to_project_user_table extends Migration
{
private const TABLE_NAME = 'project_user';
private const TABLE_COLUMN = 'status';
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn(self::TABLE_NAME, self::TABLE_COLUMN, $this->integer()->defaultValue(null));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn(self::TABLE_NAME, self::TABLE_COLUMN);
}
}

View File

@ -1,4 +1,7 @@
<?php <?php
use common\behaviors\GsCors;
$params = array_merge( $params = array_merge(
require __DIR__ . '/../../common/config/params.php', require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php', require __DIR__ . '/../../common/config/params-local.php',
@ -8,7 +11,7 @@ $params = array_merge(
return [ return [
'id' => 'app-frontend', 'id' => 'app-frontend',
'name' => 'Guild', 'name' => 'itGuild',
'basePath' => dirname(__DIR__), 'basePath' => dirname(__DIR__),
'bootstrap' => ['log'], 'bootstrap' => ['log'],
'controllerNamespace' => 'frontend\controllers', 'controllerNamespace' => 'frontend\controllers',
@ -17,10 +20,10 @@ return [
'api' => [ 'api' => [
'components' => [ 'components' => [
'user' => [ 'user' => [
'identityClass' => 'frontend\modules\api\models\User', 'identityClass' => 'frontend\modules\api\models\profile\User',
'enableAutoLogin' => true, 'enableAutoLogin' => true,
'enableSession' => false, 'enableSession' => false,
'class' => 'frontend\modules\api\models\User', 'class' => 'frontend\modules\api\models\profile\User',
//'identityCookie' => ['name' => '_identity-api', 'httpOnly' => true], //'identityCookie' => ['name' => '_identity-api', 'httpOnly' => true],
], ],
], ],
@ -47,7 +50,6 @@ return [
], ],
], ],
], ],
'request' => [ 'request' => [
'csrfParam' => '_csrf-frontend', 'csrfParam' => '_csrf-frontend',
'baseUrl' => '', 'baseUrl' => '',
@ -86,6 +88,7 @@ return [
'api/profile/<id:\d+>' => 'api/profile/index', 'api/profile/<id:\d+>' => 'api/profile/index',
'api/reports/<id:\d+>' => 'api/reports/view', 'api/reports/<id:\d+>' => 'api/reports/view',
'' => 'card/user-card/index', '' => 'card/user-card/index',
['class' => 'yii\rest\UrlRule', 'controller' => 'skills'], ['class' => 'yii\rest\UrlRule', 'controller' => 'skills'],
], ],
], ],

View File

@ -1,4 +1,4 @@
<?php <?php
return [ return [
'adminEmail' => 'admin@example.com', 'adminEmail' => 'chancellery@itguild.info',
]; ];

View File

@ -45,14 +45,13 @@ class ContactForm extends Model
/** /**
* Sends an email to the specified email address using the information collected by this model. * Sends an email to the specified email address using the information collected by this model.
* *
* @param string $email the target email address
* @return bool whether the email was sent * @return bool whether the email was sent
*/ */
public function sendEmail($email) public function sendEmail()
{ {
return Yii::$app->mailer->compose() return Yii::$app->mailer->compose()
->setTo($email) ->setTo($this->email)
->setFrom([$this->email => $this->name]) ->setFrom([Yii::$app->params['senderEmail'] => Yii::$app->params['senderName']])
->setSubject($this->subject) ->setSubject($this->subject)
->setTextBody($this->body) ->setTextBody($this->body)
->send(); ->send();

View File

@ -1,85 +0,0 @@
<?php
namespace frontend\modules\api\controllers;
use common\models\Answer;
use Yii;
use yii\filters\auth\HttpBearerAuth;
use yii\web\NotFoundHttpException;
use yii\rest\Controller;
class AnswerController extends ApiController
{
// public function behaviors(): array
// {
// $behaviors = parent::behaviors();
//
// $behaviors['authenticator']['authMethods'] = [
// HttpBearerAuth::className(),
// ];
//
// return $behaviors;
// }
public function verbs(): array
{
return [
'get-answers' => ['get'],
];
}
/**
* @OA\Get(path="/answer/get-answers",
* summary="Список ответов на вопрос",
* description="Получение списка ответов",
* security={
* {"bearerAuth": {}}
* },
* tags={"Tests"},
* @OA\Parameter(
* name="question_id",
* in="query",
* required=true,
* description="id вопроса",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает масив вопросов",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/AnswerExampleArr"),
* ),
*
* ),
* )
*
* @throws NotFoundHttpException
*/
public function actionGetAnswers(): array
{
$question_id = Yii::$app->request->get('question_id');
if(empty($question_id) or !is_numeric($question_id))
{
throw new NotFoundHttpException('Incorrect question ID');
}
$answers = Answer::activeAnswers($question_id);
if(empty($answers)) {
throw new NotFoundHttpException('Answers not found or question inactive');
}
array_walk( $answers, function(&$arr){
unset(
$arr['created_at'],
$arr['updated_at'],
$arr['answer_flag'],
$arr['status']
);
});
return $answers;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace frontend\modules\api\controllers;
use frontend\modules\api\models\company\form\CompanyIdForm;
use frontend\modules\api\services\PersonnelService;
use Yii;
class CompanyController extends ApiController
{
public PersonnelService $personnelService;
public function __construct(
$id,
$module,
PersonnelService $personnelService,
$config = []
)
{
$this->personnelService = $personnelService;
parent::__construct($id, $module, $config);
}
/**
* @OA\Get(path="/company/get-personal",
* summary="Персонал компании",
* description="Метод для получения персонала компании",
* security={
* {"bearerAuth": {}}
* },
* tags={"Company"},
* @OA\Parameter(
* name="company_id",
* description="ID компании",
* in="query",
* required=true,
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает масив объектов сотрудников",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/CompanyPersonnelDtoExampleArr"),
* ),
* ),
* )
*
* @return CompanyIdForm|array
*/
public function actionGetPersonal(): CompanyIdForm|array
{
return $this->personnelService->getPersonnel(Yii::$app->request->get());
}
}

View File

@ -2,12 +2,9 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\models\User;
use common\models\UserCard; use common\models\UserCard;
use common\services\ProfileService; use frontend\modules\api\services\ProfileService;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException; use yii\web\ServerErrorHttpException;
class ProfileController extends ApiController class ProfileController extends ApiController
@ -30,33 +27,55 @@ class ProfileController extends ApiController
]); ]);
} }
private ProfileService $profileService;
public function __construct(
$id,
$module,
ProfileService $profileService,
$config = []
)
{
$this->profileService = $profileService;
parent::__construct($id, $module, $config);
}
/** /**
* @throws NotFoundHttpException * @param null $id
* @return array|null
*/ */
public function actionIndex($id = null): ?array public function actionIndex($id = null): ?array
{ {
return ProfileService::getProfile($id, \Yii::$app->request->get()); return $this->profileService->getProfile($id, \Yii::$app->request->get());
} }
/** /**
* @throws BadRequestHttpException * @param $id
* @return array|null
* @throws ServerErrorHttpException
*/ */
public function actionProfileWithReportPermission($id): ?array public function actionProfileWithReportPermission($id): ?array
{ {
return ProfileService::getProfileWithReportPermission($id); return $this->profileService->getProfileWithReportPermission($id);
} }
/** /**
* @param $user_id
* @return array
* @throws ServerErrorHttpException * @throws ServerErrorHttpException
*/ */
public function actionGetMainData($user_id): array public function actionGetMainData($user_id): array
{ {
return ProfileService::getMainData($user_id); return $this->profileService->getMainData($user_id);
} }
/**
* @param $card_id
* @return array
*/
public function actionPortfolioProjects($card_id): array public function actionPortfolioProjects($card_id): array
{ {
return ProfileService::getPortfolioProjects($card_id); return $this->profileService->getPortfolioProjects($card_id);
} }
/** /**
@ -83,7 +102,7 @@ class ProfileController extends ApiController
*/ */
public function actionPositionsList(): array public function actionPositionsList(): array
{ {
return ProfileService::getPositionsList(); return $this->profileService->getPositionsList();
} }
/** /**

View File

@ -2,31 +2,14 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\classes\Debug;
use common\models\ProjectColumn; use common\models\ProjectColumn;
use frontend\modules\api\models\Project; use frontend\modules\api\models\project\Project;
use yii\db\ActiveRecord;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
class ProjectColumnController extends ApiController class ProjectColumnController extends ApiController
{ {
public function verbs(): array
{
return [
'get-column' => ['get'],
'get-column-list' => ['get'],
'create-column' => ['post'],
'set-priority' => ['post'],
'update-column' => ['put', 'patch'],
];
}
public function actionGetColumn()
{
}
/** /**
* *
* @OA\Get(path="/project-column/get-column-list", * @OA\Get(path="/project-column/get-column-list",
@ -55,17 +38,17 @@ class ProjectColumnController extends ApiController
* ) * )
* *
* @param $project_id * @param $project_id
* @return array|\yii\db\ActiveRecord[] * @return array|ActiveRecord[]
* @throws BadRequestHttpException * @throws BadRequestHttpException
*/ */
public function actionGetColumnList($project_id) public function actionGetColumnList($project_id): array
{ {
$project = Project::findOne($project_id); $project = Project::findOne($project_id);
if (!$project) { if (!$project) {
throw new BadRequestHttpException(json_encode(['Проект не найден'])); throw new BadRequestHttpException(json_encode(['Проект не найден']));
} }
$columns = \frontend\modules\api\models\ProjectColumn::find()->where(['project_id' => $project_id, 'status' => ProjectColumn::STATUS_ACTIVE])->all(); $columns = \frontend\modules\api\models\project\ProjectColumn::find()->where(['project_id' => $project_id, 'status' => ProjectColumn::STATUS_ACTIVE])->all();
return $columns; return $columns;
@ -183,7 +166,7 @@ class ProjectColumnController extends ApiController
* ), * ),
* ) * )
* *
* @return array|ProjectColumn|\yii\db\ActiveRecord|null * @return array|ProjectColumn|ActiveRecord|null
* @throws BadRequestHttpException * @throws BadRequestHttpException
* @throws \yii\base\InvalidConfigException * @throws \yii\base\InvalidConfigException
*/ */
@ -247,7 +230,7 @@ class ProjectColumnController extends ApiController
* ), * ),
* ) * )
* *
* @return array|Project|\yii\db\ActiveRecord * @return array|Project|ActiveRecord
* @throws BadRequestHttpException * @throws BadRequestHttpException
*/ */
public function actionSetPriority() public function actionSetPriority()

View File

@ -2,15 +2,17 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\classes\Debug;
use common\models\ProjectTaskCategory; use common\models\ProjectTaskCategory;
use common\models\Status; use common\models\Status;
use common\models\UseStatus; use common\models\UseStatus;
use frontend\modules\api\models\Manager; use frontend\modules\api\models\Manager;
use frontend\modules\api\models\Project; use frontend\modules\api\models\project\Project;
use frontend\modules\api\models\ProjectUser; use frontend\modules\api\models\project\ProjectStatistic;
use frontend\modules\api\models\project\ProjectUser;
use Yii; use Yii;
use yii\base\InvalidConfigException;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
@ -84,7 +86,7 @@ class ProjectController extends ApiController
* ) * )
* *
* @param $project_id * @param $project_id
* @return array|Project|\yii\db\ActiveRecord|null * @return array|ActiveRecord|null
*/ */
public function actionGetProject($project_id) public function actionGetProject($project_id)
{ {
@ -323,7 +325,7 @@ class ProjectController extends ApiController
* ) * )
* *
* @throws \Throwable * @throws \Throwable
* @throws \yii\base\InvalidConfigException * @throws InvalidConfigException
* @throws \yii\db\StaleObjectException * @throws \yii\db\StaleObjectException
* @throws NotFoundHttpException * @throws NotFoundHttpException
*/ */
@ -366,7 +368,7 @@ class ProjectController extends ApiController
* ), * ),
* ) * )
* *
* @return array|\yii\db\ActiveRecord * @return array|ActiveRecord
* @throws BadRequestHttpException * @throws BadRequestHttpException
*/ */
public function actionMyEmployee() public function actionMyEmployee()
@ -486,7 +488,7 @@ class ProjectController extends ApiController
* ) * )
* *
* @return Project * @return Project
* @throws \yii\base\InvalidConfigException * @throws InvalidConfigException|NotFoundHttpException
*/ */
public function actionDelUser(): Project public function actionDelUser(): Project
{ {
@ -500,4 +502,40 @@ class ProjectController extends ApiController
return $project; return $project;
} }
/**
*
* @OA\Get(path="/project/statistic",
* summary="Получить статистику проекта",
* description="Метод для получения статистики проета",
* security={
* {"bearerAuth": {}}
* },
* tags={"TaskManager"},
* @OA\Parameter(
* name="project_id",
* in="query",
* required=true,
* @OA\Schema(
* type="integer",
* default=null
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает объект статистики проекта",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ProjectStatisticExample"),
* ),
* ),
* )
*
* @param $project_id
* @return array|ActiveRecord|null
*/
public function actionStatistic($project_id): array|ActiveRecord|null
{
return ProjectStatistic::find()->where(['id' => $project_id])->one();
}
} }

View File

@ -2,47 +2,46 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\helpers\UUIDHelper; use Exception;
use common\models\Question; use frontend\modules\api\models\questionnaire\forms\QuestionnaireUuidForm;
use common\models\UserQuestionnaire; use frontend\modules\api\models\questionnaire\Question;
use frontend\modules\api\models\questionnaire\UserQuestionnaire;
use frontend\modules\api\services\UserQuestionnaireService;
use Yii; use Yii;
use yii\filters\auth\HttpBearerAuth; use yii\web\BadRequestHttpException;
use yii\rest\Controller;
use yii\web\NotFoundHttpException;
class QuestionController extends ApiController class QuestionController extends ApiController
{ {
public function behaviors() private UserQuestionnaireService $userQuestionnaireService;
{
$behaviors = parent::behaviors();
$behaviors['authenticator']['authMethods'] = [
HttpBearerAuth::className(),
];
return $behaviors;
}
public function verbs() public function __construct(
$id,
$module,
UserQuestionnaireService $userQuestionnaireService,
$config = []
)
{ {
return [ $this->userQuestionnaireService = $userQuestionnaireService;
'get-questions' => ['get'], parent::__construct($id, $module, $config);
];
} }
/** /**
* @OA\Get(path="/question/get-questions", * @OA\Get(path="/question/get-questions",
* summary="Список вопросов", * summary="Список вопросов",
* description="Получение списка вопросов", * description="Получение списка вопросов и возможные варианты ответа. Сохраняет временную метку начала тестирования,
от которой будет отсчитываться временной интервал на выполнение теста. При наличии лимита времени на выполнение теста.
При превышении лимита времени на выполнение будет возвращена ошибка: Time's up!",
* security={ * security={
* {"bearerAuth": {}} * {"bearerAuth": {}}
* }, * },
* tags={"Tests"}, * tags={"Tests"},
* @OA\Parameter( * @OA\Parameter(
* name="user", * name="uuid",
* in="query", * in="query",
* required=true, * required=true,
* description="UUID анкеты назначеной пользователю", * description="UUID анкеты назначеной пользователю",
* @OA\Schema( * @OA\Schema(
* type="integer", * type="string",
* ) * )
* ), * ),
* @OA\Response( * @OA\Response(
@ -53,40 +52,28 @@ class QuestionController extends ApiController
* @OA\Schema(ref="#/components/schemas/QuestionExampleArr"), * @OA\Schema(ref="#/components/schemas/QuestionExampleArr"),
* ), * ),
* *
*
* ), * ),
* ) * )
* *
* @throws NotFoundHttpException * @throws BadRequestHttpException
* @throws \Exception * @throws Exception
*/ */
public function actionGetQuestions(): array public function actionGetQuestions(): array
{ {
$uuid = Yii::$app->request->get('uuid'); $form = new QuestionnaireUuidForm();
if(empty($uuid) or !UUIDHelper::is_valid($uuid)) if ($form->load(Yii::$app->request->get()) && !$form->validate()) {
{ $errors = $form->errors;
throw new NotFoundHttpException('Incorrect questionnaire UUID'); throw new BadRequestHttpException(array_shift($errors)[0]);
} }
$questionnaire_id = UserQuestionnaire::getQuestionnaireId($uuid); $userQuestionnaire = UserQuestionnaire::findOne(['uuid' => $form->uuid]);
$questions = Question::activeQuestions($questionnaire_id); if (!$this->userQuestionnaireService->checkTimeLimit($userQuestionnaire)) {
if(empty($questions)) { UserQuestionnaireService::calculateScore($userQuestionnaire->uuid);
throw new NotFoundHttpException('Questions not found'); throw new BadRequestHttpException("Time's up!");
} }
array_walk( $questions, function(&$arr){ return Question::activeQuestions($userQuestionnaire->questionnaire_id);
unset(
$arr['score'],
$arr['created_at'],
$arr['updated_at'],
$arr['status'],
$arr['questionnaire_id']
);
});
return $questions;
} }
} }

View File

@ -2,10 +2,17 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\classes\Debug; use common\models\email\RegistrationEmail;
use common\models\email\ResetPasswordEmail;
use common\models\User; use common\models\User;
use common\services\EmailService;
use Exception;
use frontend\models\PasswordResetRequestForm;
use frontend\models\ResetPasswordForm;
use frontend\models\SignupForm; use frontend\models\SignupForm;
use Yii; use Yii;
use yii\base\InvalidParamException;
use yii\web\BadRequestHttpException;
class RegisterController extends ApiController class RegisterController extends ApiController
{ {
@ -16,6 +23,14 @@ class RegisterController extends ApiController
return $newBehavior; return $newBehavior;
} }
private EmailService $emailService;
public function __construct($id, $module, EmailService $emailService, $config = [])
{
$this->emailService = $emailService;
parent::__construct($id, $module, $config);
}
/** /**
* *
* @OA\Post(path="/register/sign-up", * @OA\Post(path="/register/sign-up",
@ -60,6 +75,7 @@ class RegisterController extends ApiController
if ($model->load(Yii::$app->getRequest()->getBodyParams(), '')) { if ($model->load(Yii::$app->getRequest()->getBodyParams(), '')) {
/** @var User $user */ /** @var User $user */
if ($user = $model->signup()) { if ($user = $model->signup()) {
$this->emailService->sendEmail(new RegistrationEmail($user));
return [ return [
'id' => $user->id, 'id' => $user->id,
]; ];
@ -68,4 +84,114 @@ class RegisterController extends ApiController
return null; return null;
} }
/**
*
* @OA\Post(path="/register/request-password-reset",
* summary="Запросить сброс пароля",
* description="Метод метод высылает токен сброса пароля на почтовый адрес",
* tags={"Registration"},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="multipart/form-data",
* @OA\Schema(
* required={"email"},
* @OA\Property(
* property="email",
* type="string",
* description="Электронная почта пользователя",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает true в случае успеха",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @return bool|string
*/
public function actionRequestPasswordReset()
{
$model = new PasswordResetRequestForm();
if ($model->load(Yii::$app->request->post(), '') & $model->validate()) {
/* @var $user User */
$user = User::findOne([
'status' => User::STATUS_ACTIVE,
'email' => $model->email,
]);
if (!$user) {
return false;
}
if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
$user->generatePasswordResetToken();
if (!$user->save()) {
return false;
}
}
return $this->emailService->sendEmail(new ResetPasswordEmail($user));
}
return json_encode($model->getFirstErrors());
}
/**
*
* @OA\Post(path="/register/reset-password",
* summary="Cброс пароля",
* description="Метод сброса пароля",
* tags={"Registration"},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="multipart/form-data",
* @OA\Schema(
* required={"token", "password"},
* @OA\Property(
* property="token",
* type="string",
* description="Токен сброса пароля",
* ),
* @OA\Property(
* property="password",
* type="string",
* description="Новый пароль пользователя",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @return array|string
* @throws BadRequestHttpException
*/
public function actionResetPassword()
{
try {
$model = new ResetPasswordForm(Yii::$app->request->post()['token']);
} catch (Exception $e) {
throw new BadRequestHttpException($e->getMessage());
}
if ($model->load(Yii::$app->request->post(), '') & $model->validate() & $model->resetPassword()) {
return 'Success! New password saved.';
} else {
return $model->errors;
}
}
} }

View File

@ -14,7 +14,57 @@ use yii\web\NotFoundHttpException;
class ReportsController extends ApiController class ReportsController extends ApiController
{ {
public function actionIndex($user_card_id) /**
* @OA\Get(path="/user-response/index",
* summary="Поиск отчётов по промежутку дат",
* description="Осуществляет поиск отчётов пользователя по промежутку дат",
* security={
* {"bearerAuth": {}}
* },
* tags={"Reports"},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"user_card_id"},
* @OA\Property(
* property="user_card_id",
* type="integer",
* description="Идентификатор карты(профиля) пользователя",
* nullable=false,
* ),
* @OA\Property(
* property="fromDate",
* type="DateTime",
* description="Дата начала поиска",
* nullable=false,
* ),
* @OA\Property(
* property="toDate",
* type="DateTime",
* description="Дата конца периода поиска",
* nullable=false,
* ),
* ),
* ),
* ),
*
* @OA\Response(
* response=200,
* description="Возвращает объект Запроса",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ReportsResponseExample"),
* ),
* ),
*
*
* )
*
* @param $user_card_id
* @return array
*/
public function actionIndex($user_card_id): array
{ {
$reportsModel = new ReportSearchForm(); $reportsModel = new ReportSearchForm();
@ -32,9 +82,51 @@ class ReportsController extends ApiController
} }
/** /**
* @OA\Get(path="/user-response/find-by-date",
* summary="Поиск отчётов по дате",
* description="Осуществляет поиск отчётов пользователя по дате",
* security={
* {"bearerAuth": {}}
* },
* tags={"Reports"},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"user_card_id"},
* @OA\Property(
* property="user_card_id",
* type="integer",
* description="Идентификатор карты(профиля) пользователя",
* nullable=false,
* ),
* @OA\Property(
* property="date",
* type="DateTime",
* description="Дата поиска",
* nullable=false,
* ),
* ),
* ),
* ),
*
* @OA\Response(
* response=200,
* description="Возвращает объект Запроса",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ReportsResponseExample"),
* ),
* ),
*
*
* )
*
* @return array
* @throws BadRequestHttpException
* @throws NotFoundHttpException * @throws NotFoundHttpException
*/ */
public function actionFindByDate()//: array public function actionFindByDate(): array
{ {
$reportsModel = new ReportSearchForm(); $reportsModel = new ReportSearchForm();
@ -57,7 +149,118 @@ class ReportsController extends ApiController
return $reportsModel->findByDate(); return $reportsModel->findByDate();
} }
public function actionCreate() /**
* @OA\Post(path="/reports/create",
* summary="Создание отчёта",
* description="Метод для создания нового отчёта",
* security={
* {"bearerAuth": {}}
* },
* tags={"Reports"},
* @OA\Parameter(
* name="difficulties",
* in="query",
* required=false,
* description="Описание сложностей возникших при выполнении задач",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="tomorrow",
* in="query",
* required=false,
* description="Описание планов на завтра",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="created_at",
* in="query",
* required=false,
* description="Дата создания",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="status",
* in="query",
* required=false,
* description="Статус",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="user_card_id",
* in="query",
* required=false,
* description="ID карты(профиля) пользователя",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="project_id",
* in="query",
* required=false,
* description="ID проекта",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="company_id",
* in="query",
* required=false,
* description="ID компании",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="tasks[]",
* in="query",
* required=false,
* description="Масив задач. ",
* @OA\Schema(
* type="array",
* @OA\Items(
* type="object",
* @OA\Property(
* property="task",
* description="Название задачи",
* type="string",
* ),
* @OA\Property(
* property="hours_spent",
* description="Затраченное количество часов",
* type="string",
* ),
* @OA\Property(
* property="minutes_spent",
* description="Затраченное количество минут",
* type="string",
* )
* )
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает объект Запроса",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ReportsResponseCreateExample"),
* ),
* ),
* )
*
* @return array
* @throws BadRequestHttpException
*/
public function actionCreate(): array
{ {
$params = Yii::$app->request->post(); $params = Yii::$app->request->post();
if (!isset($params['tasks'])){ if (!isset($params['tasks'])){
@ -93,6 +296,41 @@ class ReportsController extends ApiController
return array_merge($reportsModel->toArray()); return array_merge($reportsModel->toArray());
} }
/**
* @OA\Get(path="/user-response/delete",
* summary="Удаление отчёта",
* description="Осуществляет удаление отчёта",
* security={
* {"bearerAuth": {}}
* },
* tags={"Reports"},
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"id"},
* @OA\Property(
* property="id",
* type="integer",
* description="Идентификатор отчётая",
* nullable=false,
* ),
* ),
* ),
* ),
*
* @OA\Response(
* response=200,
* description="Возвращает true в случае успеха",
* ),
* )
*
* @return bool
* @throws NotFoundHttpException
* @throws \Throwable
* @throws \yii\db\StaleObjectException
*/
public function actionDelete() public function actionDelete()
{ {
$id = Yii::$app->request->get('id'); $id = Yii::$app->request->get('id');
@ -110,6 +348,82 @@ class ReportsController extends ApiController
return true; return true;
} }
/**
* @OA\Get(path="/reports/update",
* summary="Обновление отчёта",
* description="Метод для Обновления отчёта",
* security={
* {"bearerAuth": {}}
* },
* tags={"Reports"},
* @OA\Parameter(
* name="id",
* in="query",
* required=true,
* description="ID отчёта",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="created_at",
* in="query",
* required=false,
* description="Дата создания (yyyy-mm-dd)",
* @OA\Schema(
* type="DateTime",
* )
* ),
* @OA\Parameter(
* name="today",
* in="query",
* required=false,
* description="Сделанное сегодня",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="difficulties",
* in="query",
* required=false,
* description="Описание сложностей возникших при выполнении задач",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="tomorrow",
* in="query",
* required=false,
* description="Описание планов на завтра",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="status",
* in="query",
* required=false,
* description="Статус",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает объект Запроса",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ReportsResponseCreateExample"),
* ),
* ),
* )
*
* @return array
* @throws BadRequestHttpException
* @throws NotFoundHttpException
*/
public function actionUpdate(): array public function actionUpdate(): array
{ {
$params = Yii::$app->request->get(); $params = Yii::$app->request->get();
@ -135,7 +449,11 @@ class ReportsController extends ApiController
} }
/** /**
* @throws NotFoundHttpException * @param $fromDate
* @param $toDate
* @param $user_card_id
* @return array|array[]|object|object[]|string[]
* @throws BadRequestHttpException
*/ */
public function actionReportsByDate($fromDate, $toDate, $user_card_id) public function actionReportsByDate($fromDate, $toDate, $user_card_id)
{ {
@ -170,5 +488,4 @@ class ReportsController extends ApiController
} }
return true; return true;
} }
} }

View File

@ -0,0 +1,143 @@
<?php
namespace frontend\modules\api\controllers;
use frontend\modules\api\models\resume\forms\ChangeResumeForm;
use frontend\modules\api\models\resume\Resume;
use frontend\modules\api\services\ResumeService;
use Yii;
use yii\web\BadRequestHttpException;
class ResumeController extends ApiController
{
public ResumeService $resumeService;
public function __construct(
$id,
$module,
ResumeService $resumeService,
$config = []
)
{
$this->resumeService = $resumeService;
parent::__construct($id, $module, $config);
}
/**
* @OA\Get(path="/resume",
* summary="Резюме пользователя",
* description="Получение резюме пользователя",
* security={
* {"bearerAuth": {}}
* },
* tags={"Resume"},
* @OA\Parameter(
* name="userId",
* description="Метод для получение резюме. userId - обязателен, в случае его отсудствия будет возвращено резюме текущего пользователя",
* in="query",
* required=false,
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает объект Резюме",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/Resume"),
* ),
* ),
* )
*
* @param int|null $userId
* @return Resume|null
*/
public function actionIndex(int $userId = null): ?Resume
{
return Resume::findOne($userId ?? Yii::$app->user->identity->id);
}
/**
*
* @OA\Put(path="/resume/edit-skills",
* summary="Изменить скилы",
* description="Метод полностью удалит старые скилы и используя переданые id скилов запишет новые",
* security={
* {"bearerAuth": {}}
* },
* tags={"Resume"},
*
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="json",
* @OA\Schema(
* required={"UserCard"},
* @OA\Property(
* property="UserCard",
* type="object",
* @OA\Property(
* property="skill",
* type="array",
* @OA\Items(
* type="integer",
* example={1,2,3,4}
* ),
* ),
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* ),
* )
* )
*
* @return array|ChangeResumeForm
* @throws BadRequestHttpException
*/
public function actionEditSkills()
{
return $this->resumeService->editSkills(Yii::$app->request->post(), Yii::$app->user->identity->getId());
}
/**
*
* @OA\Put(path="/resume/edit-text",
* summary="Изменить резюме",
* description="Метод для изменения текста резюме",
* security={
* {"bearerAuth": {}}
* },
* tags={"Resume"},
*
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"resume"},
* @OA\Property(
* property="resume",
* type="string",
* description="Текст резюме",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* ),
* )
* )
*
* @return array|ChangeResumeForm
* @throws BadRequestHttpException
*/
public function actionEditText(): ChangeResumeForm|array
{
return $this->resumeService->editText(Yii::$app->request->post(), Yii::$app->user->identity->getId());
}
}

View File

@ -2,31 +2,35 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\classes\Debug;
use common\models\ProjectTask; use common\models\ProjectTask;
use common\models\ProjectTaskUser; use common\models\ProjectTaskUser;
use common\models\User; use common\models\User;
use common\services\TaskService; use frontend\modules\api\models\project\ProjectColumn;
use frontend\modules\api\models\ProjectColumn; use frontend\modules\api\services\TaskService;
use Yii; use Yii;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\data\ActiveDataProvider;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException; use yii\web\ServerErrorHttpException;
class TaskController extends ApiController class TaskController extends ApiController
{ {
public function verbs(): array /**
* @var TaskService
*/
private TaskService $taskService;
/**
* @param $id
* @param $module
* @param TaskService $taskService
* @param array $config
*/
public function __construct($id, $module, TaskService $taskService, $config = [])
{ {
return [ $this->taskService = $taskService;
'get-task' => ['get'], parent::__construct($id, $module, $config);
'get-task-list' => ['get'],
'get-user-tasks' => ['get'],
'create-task' => ['post'],
'update-task' => ['put', 'patch'],
'add-user-to-task' => ['post'],
'del-user' => ['delete'],
];
} }
/** /**
@ -72,7 +76,12 @@ class TaskController extends ApiController
* @OA\Property( * @OA\Property(
* property="priority", * property="priority",
* type="integer", * type="integer",
* description="Приоритет задачи", * description="Приоритет задачи.",
* ),
* @OA\Property(
* property="execution_priority",
* type="integer",
* description="Приоритет выполнения задачи (0 - low, 1 - medium, 2 - high)",
* ), * ),
* @OA\Property( * @OA\Property(
* property="column_id", * property="column_id",
@ -112,7 +121,7 @@ class TaskController extends ApiController
$request['user_id'] = Yii::$app->user->id; $request['user_id'] = Yii::$app->user->id;
} }
$taskModel = TaskService::createTask($request); $taskModel = $this->taskService->createTask($request);
if ($taskModel->errors) { if ($taskModel->errors) {
throw new ServerErrorHttpException(json_encode($taskModel->errors)); throw new ServerErrorHttpException(json_encode($taskModel->errors));
} }
@ -138,6 +147,15 @@ class TaskController extends ApiController
* ) * )
* ), * ),
* @OA\Parameter( * @OA\Parameter(
* name="user_id",
* description="При передаче этого параметера вернёт все задачи на проекте для пользователя с заданным id",
* in="query",
* required=false,
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="expand", * name="expand",
* in="query", * in="query",
* example="column,timers,mark", * example="column,timers,mark",
@ -158,17 +176,9 @@ class TaskController extends ApiController
* *
* @throws NotFoundHttpException * @throws NotFoundHttpException
*/ */
public function actionGetTaskList($project_id): array public function actionGetTaskList($project_id, $user_id = null): array
{ {
$tasks = array(); $tasks = $this->taskService->getTaskListByProject($project_id, $user_id);
if ($project_id) {
if (empty($project_id) or !is_numeric($project_id)) {
throw new NotFoundHttpException('Incorrect project ID');
}
$tasks = TaskService::getTaskListByProject($project_id);
} else {
$tasks = TaskService::getTaskList($project_id);
}
if (empty($tasks)) { if (empty($tasks)) {
throw new NotFoundHttpException('The project does not exist or there are no tasks for it'); throw new NotFoundHttpException('The project does not exist or there are no tasks for it');
@ -176,6 +186,59 @@ class TaskController extends ApiController
return $tasks; return $tasks;
} }
/**
*
* @OA\Get(path="/task/get-archive-task",
* summary="Получить список архивных задач по проекту",
* description="Метод для получения архивных задач по проекту",
* security={
* {"bearerAuth": {}}
* },
* tags={"TaskManager"},
* @OA\Parameter(
* name="project_id",
* in="query",
* required=true,
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="user_id",
* in="query",
* required=false,
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="expand",
* in="query",
* example="column,timers,mark",
* description="В этом параметре по необходимости передаются поля, которые нужно добавить в ответ сервера, сейчас доступно только поля <b>column</b>, <b>timers</b> и <b>mark</b>",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает массив объектов Задач",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/ProjectTaskExample"),
* ),
* ),
* )
*
* @param $project_id
* @param null $user_id
* @return array
*/
public function actionGetArchiveTask($project_id, $user_id = null): array
{
return $this->taskService->getArchiveTask($project_id, $user_id);
}
/** /**
* *
* @OA\Get(path="/task/get-user-tasks", * @OA\Get(path="/task/get-user-tasks",
@ -218,15 +281,7 @@ class TaskController extends ApiController
*/ */
public function actionGetUserTasks($user_id): array public function actionGetUserTasks($user_id): array
{ {
$tasks = array(); $tasks = $this->taskService->getTaskListByUser($user_id);
if ($user_id) {
if (empty($user_id) or !is_numeric($user_id)) {
throw new NotFoundHttpException('Incorrect project ID');
}
$tasks = TaskService::getTaskListByUser($user_id);
} else {
$tasks = TaskService::getTaskList($user_id);
}
if (empty($tasks)) { if (empty($tasks)) {
throw new NotFoundHttpException('The project does not exist or there are no tasks for it'); throw new NotFoundHttpException('The project does not exist or there are no tasks for it');
@ -278,7 +333,7 @@ class TaskController extends ApiController
throw new NotFoundHttpException('Incorrect task ID'); throw new NotFoundHttpException('Incorrect task ID');
} }
$task = TaskService::getTask($task_id); $task = $this->taskService->getTask($task_id);
if (empty($task)) { if (empty($task)) {
throw new NotFoundHttpException('The task does not exist'); throw new NotFoundHttpException('The task does not exist');
} }
@ -367,11 +422,11 @@ class TaskController extends ApiController
public function actionUpdateTask(): ?ProjectTask public function actionUpdateTask(): ?ProjectTask
{ {
$params = array_diff(\Yii::$app->request->getBodyParams(), [null, '']); $params = array_diff(\Yii::$app->request->getBodyParams(), [null, '']);
if (empty ($params['task_id']) or !TaskService::taskExists($params['task_id'])) { if (empty ($params['task_id']) or !$this->taskService->taskExists($params['task_id'])) {
throw new NotFoundHttpException('The task does not exist'); throw new NotFoundHttpException('The task does not exist');
} }
$modelTask = TaskService::updateTask($params); $modelTask = $this->taskService->updateTask($params);
if (!empty($modelTask->hasErrors())) { if (!empty($modelTask->hasErrors())) {
throw new ServerErrorHttpException(json_encode($modelTask->errors)); throw new ServerErrorHttpException(json_encode($modelTask->errors));
} }
@ -430,7 +485,7 @@ class TaskController extends ApiController
throw new NotFoundHttpException('User not found'); throw new NotFoundHttpException('User not found');
} }
if (empty ($request['task_id']) or !TaskService::taskExists($request['task_id'])) { if (empty ($request['task_id']) or !$this->taskService->taskExists($request['task_id'])) {
throw new NotFoundHttpException('The task does not exist'); throw new NotFoundHttpException('The task does not exist');
} }
@ -501,13 +556,13 @@ class TaskController extends ApiController
throw new NotFoundHttpException('User not found'); throw new NotFoundHttpException('User not found');
} }
if (empty ($request['task_id']) or !TaskService::taskExists($request['task_id'])) { if (empty ($request['task_id']) or !$this->taskService->taskExists($request['task_id'])) {
throw new NotFoundHttpException('The task does not exist'); throw new NotFoundHttpException('The task does not exist');
} }
ProjectTaskUser::deleteAll(['task_id' => $request['task_id'], 'user_id' => $request['user_id']]); ProjectTaskUser::deleteAll(['task_id' => $request['task_id'], 'user_id' => $request['user_id']]);
return TaskService::getTask($request['task_id']); return $this->taskService->getTask($request['task_id']);
} }
/** /**
@ -577,4 +632,69 @@ class TaskController extends ApiController
return $column; return $column;
} }
/**
*
* @OA\Get(path="/task/import",
* summary="Экспорт задач",
* description="Метод импорта задач в xlsx",
* security={
* {"bearerAuth": {}}
* },
* tags={"TaskManager"},
* @OA\Parameter(
* name="companyId",
* in="query",
* description="ID компании",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="userId",
* in="query",
* description="ID исполнителя задачи",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="projectId",
* in="query",
* description="ID проекта",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="fromDate",
* in="query",
* example="2023-11-09",
* description="Поиск задач с указанной даты",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="toDate",
* in="query",
* example="2023-11-09",
* description="Поиск задач до указанной даты",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает задачи в xlsx файле",
* ),
* )
*
* @return string|void
* @throws BadRequestHttpException
*/
public function actionImport()
{
return $this->taskService->importTasks(Yii::$app->request->get());
}
} }

View File

@ -3,16 +3,13 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\behaviors\GsCors;
use common\classes\Debug;
use common\models\User; use common\models\User;
use frontend\modules\api\models\LoginForm; use frontend\modules\api\models\profile\forms\ProfileChangeEmailForm;
use frontend\modules\api\models\profile\forms\ProfileChangePersonalDataForm;
use frontend\modules\api\services\UserService;
use Yii; use Yii;
use yii\filters\ContentNegotiator; use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\rest\ActiveController;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\Response;
class UserController extends ApiController class UserController extends ApiController
{ {
@ -26,28 +23,19 @@ class UserController extends ApiController
} }
return $behaviors; return $behaviors;
// return ArrayHelper::merge(parent::behaviors(), [ }
// [
// 'class' => ContentNegotiator::class, private UserService $userService;
// 'formats' => [
// 'application/json' => Response::FORMAT_JSON, public function __construct(
// ], $id,
// ], $module,
// 'corsFilter' => [ UserService $userService,
// 'class' => GsCors::class, $config = []
// 'cors' => [ )
// 'Origin' => ['*'], {
// //'Access-Control-Allow-Credentials' => true, $this->userService = $userService;
// 'Access-Control-Allow-Headers' => [ parent::__construct($id, $module, $config);
// 'Access-Control-Allow-Origin',
// 'Content-Type',
// 'Access-Control-Allow-Headers',
// 'Authorization',
// 'X-Requested-With'
// ],
// ]
// ],
// ]);
} }
public function actions() public function actions()
@ -59,28 +47,23 @@ class UserController extends ApiController
unset($actions['delete']); unset($actions['delete']);
} }
// protected function verbs(){ public function verbs(): array
// return [
// 'login' => ['POST']
// ];
// }
public function actionLogin()
{ {
$model = new LoginForm(); return [
if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->login()) { 'change-personalData' => ['put', 'patch'],
/** @var User $user */ 'change-email' => ['put', 'patch'],
$user = $model->getUser(); 'change-password' => ['put', 'patch'],
return [ ];
'access_token' => $model->login(), }
'access_token_expired_at' => $model->getUser()->getTokenExpiredAt(),
'id' => $user->id, /**
'status' => $user->userCard->status ?? null, * @return array
'card_id' => $user->userCard->id ?? null, * @throws BadRequestHttpException
]; * @throws InvalidConfigException
} else { */
throw new BadRequestHttpException(json_encode($model->errors)); public function actionLogin(): array
} {
return $this->userService->login(Yii::$app->getRequest()->getBodyParams());
} }
/** /**
@ -101,16 +84,128 @@ class UserController extends ApiController
* ), * ),
* ) * )
* *
* @return \frontend\modules\api\models\User * @return \frontend\modules\api\models\profile\User
* @throws BadRequestHttpException * @throws BadRequestHttpException
*/ */
public function actionMe(): \frontend\modules\api\models\User public function actionMe(): \frontend\modules\api\models\profile\User
{ {
$user = \frontend\modules\api\models\User::findOne(Yii::$app->user->id); return $this->userService->findCurrentUser();
if (!$user){ }
throw new BadRequestHttpException("User not found");
}
return $user; /**
*
* @OA\Put(path="/user/change-email",
* summary="Изменить email адрес",
* description="Метод для изменения email адреса пользователя",
* security={
* {"bearerAuth": {}}
* },
* tags={"User"},
*
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"newEmail"},
* @OA\Property(
* property="newEmail",
* type="string",
* description="Новый email адрес",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* ),
* )
* )
*
* @return ProfileChangeEmailForm|string[]
*/
public function actionChangeEmail()
{
return $this->userService->changeEmail(Yii::$app->request->post());
}
/**
*
* @OA\Put(path="/user/change-password",
* summary="Изменить пароль",
* description="Метод для изменения пароля пользователя",
* security={
* {"bearerAuth": {}}
* },
* tags={"User"},
*
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"password", "newPassword"},
* @OA\Property(
* property="password",
* type="string",
* description="Старый пароль",
* ),
* @OA\Property(
* property="newPassword",
* type="string",
* description="Новый пароль",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* ),
* )
* )
*
* @return ProfileChangeEmailForm|string[]
*/
public function actionChangePassword()
{
return $this->userService->changePassword(Yii::$app->request->post());
}
/**
*
* @OA\Put(path="/user/change-personal-data",
* summary="Изменить логин",
* description="Метод для изменения логина пользователя",
* security={
* {"bearerAuth": {}}
* },
* tags={"User"},
*
* @OA\RequestBody(
* @OA\MediaType(
* mediaType="application/x-www-form-urlencoded",
* @OA\Schema(
* required={"newUsername"},
* @OA\Property(
* property="newUsername",
* type="string",
* description="Новый логин",
* ),
* ),
* ),
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* ),
* )
* )
*
* @return ProfileChangePersonalDataForm|string[]
* @throws \Exception
*/
public function actionChangePersonalData()
{
return $this->userService->changeChangePersonalData(Yii::$app->request->post());
} }
} }

View File

@ -2,7 +2,9 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\services\UserQuestionnaireService; use frontend\modules\api\models\questionnaire\UserQuestionnaire;
use frontend\modules\api\services\UserQuestionnaireService;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException; use yii\web\ServerErrorHttpException;
@ -13,14 +15,11 @@ class UserQuestionnaireController extends ApiController
public function behaviors(): array public function behaviors(): array
{ {
return ArrayHelper::merge(parent::behaviors(), [ return ArrayHelper::merge(parent::behaviors(), [
'verbs' => [ 'verbs' => [
'class' => \yii\filters\VerbFilter::class, 'class' => \yii\filters\VerbFilter::class,
'actions' => [ 'actions' => [
'questionnaires-list' => ['get'], 'questionnaires-list' => ['get'],
'questionnaire-completed' => ['get'], 'questionnaire-completed' => ['get'],
'get-points-number' => ['get'],
'get-question-number' => ['get'],
], ],
] ]
]); ]);
@ -72,7 +71,7 @@ class UserQuestionnaireController extends ApiController
/** /**
* @OA\Get(path="/user-questionnaire/questionnaire-completed", * @OA\Get(path="/user-questionnaire/questionnaire-completed",
* summary="Проверка теста", * summary="Проверка теста",
* description="Выполнения проверки теста", * description="Выполнение проверки теста",
* security={ * security={
* {"bearerAuth": {}} * {"bearerAuth": {}}
* }, * },
@ -97,9 +96,9 @@ class UserQuestionnaireController extends ApiController
* ) * )
* *
* @throws NotFoundHttpException * @throws NotFoundHttpException
* @throws ServerErrorHttpException * @throws ServerErrorHttpException|InvalidConfigException
*/ */
public function actionQuestionnaireCompleted($user_questionnaire_uuid) public function actionQuestionnaireCompleted($user_questionnaire_uuid): UserQuestionnaire
{ {
$userQuestionnaireModel = UserQuestionnaireService::calculateScore($user_questionnaire_uuid); $userQuestionnaireModel = UserQuestionnaireService::calculateScore($user_questionnaire_uuid);
if ($userQuestionnaireModel->errors) { if ($userQuestionnaireModel->errors) {
@ -107,90 +106,4 @@ class UserQuestionnaireController extends ApiController
} }
return $userQuestionnaireModel; return $userQuestionnaireModel;
} }
/**
* @OA\Get(path="/user-questionnaire/get-points-number",
* summary="Количество балов в тесте",
* description="Возвращает максимальное количество балов за тест",
* security={
* {"bearerAuth": {}}
* },
* tags={"Tests"},
* @OA\Parameter(
* name="user_questionnaire_uuid",
* in="query",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает максимально возможное количество балов за тест",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="sum_point",
* type="integer",
* example="61",
* ),
* ),
* ),
*
* ),
* )
* @throws ServerErrorHttpException
*/
public function actionGetPointsNumber($user_questionnaire_uuid)
{
$questionPointsNumber = UserQuestionnaireService::getPointsNumber($user_questionnaire_uuid);
if (empty($questionPointsNumber)) {
throw new ServerErrorHttpException('Question points not found!');
}
return $questionPointsNumber;
}
/**
* @OA\Get(path="/user-questionnaire/get-question-number",
* summary="Число вопросов в тесте",
* description="Возвращает число вопросов в тесте",
* security={
* {"bearerAuth": {}}
* },
* tags={"Tests"},
* @OA\Parameter(
* name="user_questionnaire_uuid",
* in="query",
* required=true,
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает число вопросов в тесте",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="question_number",
* type="integer",
* example="61",
* ),
* ),
* ),
*
* ),
* )
* @throws ServerErrorHttpException
*/
public function actionGetQuestionNumber($user_questionnaire_uuid)
{
$questionNumber = UserQuestionnaireService::getQuestionNumber($user_questionnaire_uuid);
if (empty($questionNumber)) {
throw new ServerErrorHttpException('Question number not found!');
}
return $questionNumber;
}
} }

View File

@ -2,8 +2,9 @@
namespace frontend\modules\api\controllers; namespace frontend\modules\api\controllers;
use common\models\UserResponse; use frontend\modules\api\models\questionnaire\UserQuestionnaire;
use common\services\UserResponseService; use frontend\modules\api\services\UserQuestionnaireService;
use frontend\modules\api\services\UserResponseService;
use Yii; use Yii;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
@ -11,86 +12,24 @@ use yii\web\ServerErrorHttpException;
class UserResponseController extends ApiController class UserResponseController extends ApiController
{ {
public function verbs(): array private UserQuestionnaireService $userQuestionnaireService;
{
return [
'set-response' => ['post'],
'set-responses' => ['post'],
];
}
/** public function __construct(
* @OA\Post(path="/user-response/set-response", $id,
* summary="Добавить ответ пользователя", $module,
* description="Добавление ответа на вопрос от пользователя", UserQuestionnaireService $userQuestionnaireService,
* security={ $config = []
* {"bearerAuth": {}} )
* },
* tags={"Tests"},
* @OA\Parameter(
* name="user_id",
* in="query",
* required=true,
* description="ID пользователя",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="question_id",
* in="query",
* required=true,
* description="ID вопроса",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="response_body",
* in="query",
* required=true,
* description="Ответ пользователя",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Parameter(
* name="user_questionnaire_uuid",
* in="query",
* required=true,
* description="UUID анкеты назначенной пользователю",
* @OA\Schema(
* type="string",
* )
* ),
*
*
* @OA\Response(
* response=200,
* description="Возвращает ответ",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/UserResponseExample"),
* ),
* ),
* )
*
* @throws InvalidConfigException
* @throws ServerErrorHttpException|BadRequestHttpException
*/
public function actionSetResponse(): UserResponse
{ {
$userResponseModel = UserResponseService::createUserResponse(Yii::$app->getRequest()->getBodyParams()); $this->userQuestionnaireService = $userQuestionnaireService;
if ($userResponseModel->errors) { parent::__construct($id, $module, $config);
throw new ServerErrorHttpException(json_encode($userResponseModel->errors));
}
return $userResponseModel;
} }
/** /**
* @OA\Post(path="/user-response/set-responses", * @OA\Post(path="/user-response/set-responses",
* summary="Добавить массив ответов пользователя", * summary="Добавить массив ответов пользователя",
* description="Добавление массива ответов на вопросы от пользователя", * description="Добавление массива ответов на вопросы от пользователя. При наличии лимита времени на выполнение теста,
будет проведена проверка. При превышении лимита времени на выполнение будет возвращена ошибка: Time's up!",
* security={ * security={
* {"bearerAuth": {}} * {"bearerAuth": {}}
* }, * },
@ -127,7 +66,7 @@ class UserResponseController extends ApiController
* *
* @OA\Response( * @OA\Response(
* response=200, * response=200,
* description="Возвращает объект Запроса", * description="Возвращает масив ответов",
* @OA\MediaType( * @OA\MediaType(
* mediaType="application/json", * mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/UserResponseExampleArr"), * @OA\Schema(ref="#/components/schemas/UserResponseExampleArr"),
@ -135,12 +74,25 @@ class UserResponseController extends ApiController
* ), * ),
* ) * )
* *
* @return array
* @throws BadRequestHttpException
* @throws InvalidConfigException * @throws InvalidConfigException
* @throws ServerErrorHttpException|BadRequestHttpException * @throws ServerErrorHttpException
* @throws \yii\web\NotFoundHttpException
*/ */
public function actionSetResponses(): array public function actionSetResponses(): array
{ {
$userResponseModels = UserResponseService::createUserResponses(Yii::$app->getRequest()->getBodyParams()); $uuid = Yii::$app->request->post('user_questionnaire_uuid');
$userResponses = Yii::$app->request->post('userResponses');
$userQuestionnaire = UserQuestionnaire::findOne(['uuid' => $uuid]);
if (!$this->userQuestionnaireService->checkTimeLimit($userQuestionnaire)) {
UserQuestionnaireService::calculateScore($userQuestionnaire->uuid);
throw new BadRequestHttpException("Time's up!");
}
$userResponseModels = UserResponseService::createUserResponses($userResponses, $uuid);
foreach ($userResponseModels as $model) { foreach ($userResponseModels as $model) {
if ($model->errors) { if ($model->errors) {
throw new ServerErrorHttpException(json_encode($model->errors)); throw new ServerErrorHttpException(json_encode($model->errors));

View File

@ -0,0 +1,268 @@
<?php
namespace frontend\modules\api\controllers;
use Exception;
use frontend\modules\api\models\profile\User;
use frontend\modules\api\models\tg_bot\forms\TgBotDialogForm;
use frontend\modules\api\models\tg_bot\UserTgBotToken;
use frontend\modules\api\services\UserTgBotTokenService;
use Yii;
class UserTgBotController extends ApiController
{
/**
* @var UserTgBotTokenService
*/
private UserTgBotTokenService $userTgBotTokenService;
public function behaviors()
{
$behaviors = parent::behaviors();
if($this->action->id == "auth"){
unset($behaviors['authenticator']);
}
return $behaviors;
}
public function __construct(
$id,
$module,
UserTgBotTokenService $userTgBotTokenService,
$config = []
)
{
$this->userTgBotTokenService = $userTgBotTokenService;
parent::__construct($id, $module, $config);
}
/**
* @OA\Get(path="/user-tg-bot/get-token",
* summary="Токен ТГ бота",
* description="Метод для возвращает токен для ТГ бота",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Response(
* response=200,
* description="Возвращает объект токен ТГ бота",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(ref="#/components/schemas/UserTgBotTokenExample"),
* ),
* ),
* )
*
* @return UserTgBotToken
* @throws Exception
*/
public function actionGetToken(): UserTgBotToken
{
return $this->userTgBotTokenService->getToken(Yii::$app->user->id);
}
/**
*
* @OA\Get(path="/user-tg-bot/get-user",
* summary="Получить данные пользователя",
* description="Метод для получения данныех пользователя по токену ТГ бота",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Parameter(
* name="token",
* in="query",
* example="HDAS7J",
* required=true,
* description="Токен ТГ бота",
* @OA\Schema(
* type="string",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает данные пользователя",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @param string $token
* @return User|string[]
* @throws Exception
*/
public function actionGetUser(string $token)
{
return $this->userTgBotTokenService->getUserByToken($token);
}
/**
*
* @OA\Post(path="/user-tg-bot/set-dialog",
* summary="Сохранить новый id диалога",
* description="Метод создает новую запись с id пользователя и id диалога",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Parameter(
* name="userId",
* in="query",
* example="1",
* required=true,
* description="id пользователя",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Parameter(
* name="dialogId",
* in="query",
* example="2355",
* required=true,
* description="id диалога",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @return TgBotDialogForm|string[]
* @throws Exception
*/
public function actionSetDialog()
{
return $this->userTgBotTokenService->createDialog(Yii::$app->request->post());
}
/**
*
* @OA\Get(path="/user-tg-bot/dialog/get-dialog-id",
* summary="Получить id диалога по id пользователя",
* description="Метод для получения id пользователя по id пользователя",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Parameter(
* name="userId",
* in="query",
* example="1",
* required=true,
* description="id пользователя",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает dialog_id",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @param string $userId
* @return array
* @throws Exception
*/
public function actionGetDialogId(string $userId): array
{
return $this->userTgBotTokenService->getDialogIdByUserId($userId);
}
/**
*
* @OA\Get(path="/user-tg-bot/get-user-id",
* summary="Получить id пользователя по id диалога",
* description="Метод для получения id пользователя по id диалога",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Parameter(
* name="dialogId",
* in="query",
* example="225",
* required=true,
* description="id диалога",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает user_id",
* @OA\MediaType(
* mediaType="application/json",
* ),
* ),
* )
*
* @param string $dialogId
* @return array
* @throws Exception
*/
public function actionGetUserId(string $dialogId): array
{
return $this->userTgBotTokenService->getUserIdByDialogId($dialogId);
}
/**
*
* @OA\Post(path="/user-tg-bot/auth",
* summary="Аутентификация",
* description="Метод производит аутентификацию пользователя по токену ТГ бта",
* security={
* {"bearerAuth": {}}
* },
* tags={"TgBot"},
* @OA\Parameter(
* name="token",
* in="query",
* example="1",
* required=true,
* description="токен пользователя",
* @OA\Schema(
* type="integer",
* )
* ),
* @OA\Response(
* response=200,
* description="Возвращает сообщение об успехе",
* @OA\MediaType(
* mediaType="application/json",
* * @OA\Schema(
* schema="schemae_5cfb24156100e_category",
* @OA\Property(property="access_token",type="string",description="Category ID",example="HclquHysW2Y6LecQfM_ZZTjL4kBz-jOi"),
* @OA\Property(property="access_token_expired_at",type="dateTime",description="Expired at",example="2023-11-08"),
* @OA\Property(property="id",type="integer",description="ID",example=1),
* @OA\Property(property="status",type="integer",description="status",example=1),
* @OA\Property(property="card_id",type="integer",description="Card ID",example=1),
* ),
* ),
* ),
* )
*
* @return array
* @throws \yii\web\BadRequestHttpException
*/
public function actionAuth()
{
return $this->userTgBotTokenService->auth(Yii::$app->request->post());
}
}

View File

@ -0,0 +1,132 @@
<?php
namespace frontend\modules\api\models;
/**
* @OA\Schema(
* schema="Reports",
* @OA\Property(
* property="difficulties",
* type="string",
* description="Описание сложностей возникших при выполнении задач"
* ),
* @OA\Property(
* property="tomorrow",
* type="string",
* description="Описание планов на завтра"
* ),
*
* @OA\Property(
* property="created_at",
* type="datetime",
* example="2023-04-07 02:09:42",
* description="Дата создания"
* ),
* @OA\Property(
* property="status",
* type="integer",
* example="1",
* description="Статус"
* ),
* @OA\Property(
* property="user_card_id",
* type="integer",
* example=19,
* description="ID карты(профиля) пользователя"
* ),
* @OA\Property(
* property="project_id",
* type="integer",
* example=1,
* description="ID проекта"
* ),
* @OA\Property(
* property="company_id",
* type="integer",
* example=1,
* description="ID компании",
* ),
*)
*
*
* @OA\Schema(
* schema="ReportsResponseCreateExample",
* type="array",
* @OA\Items(
* type="object",
* @OA\Property(
* property="difficulties",
* type="string",
* ),
* @OA\Property(
* property="tomorrow",
* type="string",
* ),
* @OA\Property(
* property="created_at",
* type="datetime",
* ),
* @OA\Property(
* property="status",
* type="integer",
* ),
* @OA\Property(
* property="user_card_id",
* type="integer",
* ),
* @OA\Property(
* property="project_id",
* type="integer",
* ),
* @OA\Property(
* property="company_id",
* type="integer",
* ),
* ),
*)
*
* @OA\Schema(
* schema="ReportsResponseExample",
* type="array",
* @OA\Items(
* type="object",
* @OA\Property(
* property="difficulties",
* type="string",
* ),
* @OA\Property(
* property="tomorrow",
* type="string",
* ),
* @OA\Property(
* property="created_at",
* type="datetime",
* ),
* @OA\Property(
* property="status",
* type="integer",
* ),
* @OA\Property(
* property="user_card_id",
* type="integer",
* ),
* @OA\Property(
* property="project_id",
* type="integer",
* ),
* @OA\Property(
* property="company_id",
* type="integer",
* ),
* @OA\Property(
* property="task",
* ref="#/components/schemas/ProjectTaskReportsExample",
* ),
* ),
*)
*
*/
class Reports extends \common\models\Reports
{
}

View File

@ -0,0 +1,74 @@
<?php
namespace frontend\modules\api\models;
/**
*
* @OA\Schema(
* schema="UserCardPortfolioProjects",
* @OA\Property(
* property="title",
* type="string",
* description="Название"
* ),
* @OA\Property(
* property="description",
* type="string",
* description="Описание проекта"
* ),
* @OA\Property(
* property="main_stack",
* type="string",
* description="Основная технология"
* ),
* @OA\Property(
* property="additional_stack",
* type="string",
* description="Дополнительные технологии"
* ),
* @OA\Property(
* property="link",
* type="string",
* description="Ссылка"
* ),
*)
*
* @OA\Schema(
* schema="UserCardPortfolioProjectsExample",
* type="array",
* @OA\Items(
* ref="#/components/schemas/UserCardPortfolioProjects",
* ),
*)
*
* @property Skill $mainStack
*/
class UserCardPortfolioProjects extends \common\models\UserCardPortfolioProjects
{
public function fields(): array
{
return [
'title',
'description',
'main_stack' => function () {
return $this->mainStack->name;
},
'additional_stack',
'link',
];
}
/**
* @return string[]
*/
public function extraFields(): array
{
return [];
}
public function getMainStack()
{
return $this->hasOne(Skill::class, ['id' => 'main_stack']);
}
}

View File

@ -1,103 +0,0 @@
<?php
namespace frontend\modules\api\models;
/**
*
* @OA\Schema(
* schema="UserQuestionnaire",
* @OA\Property(
* property="user_id",
* type="int",
* example=1,
* description="Идентификатор пользователя"
* ),
* @OA\Property(
* property="uuid",
* type="string",
* example="d222f858-60fd-47fb-8731-dc9d5fc384c5",
* description="uuid"
* ),
* @OA\Property(
* property="score",
* type="int",
* example="11",
* description="Количество балов за тест"
* ),
* @OA\Property(
* property="status",
* type="int",
* example="2",
* description="статус файла"
* ),
* @OA\Property(
* property="percent_correct_answers",
* type="float",
* example="0.25",
* description="Процент правильных ответов"
* ),
* @OA\Property(
* property="testing_date",
* type="string",
* example="2022-03-17 11:14:22",
* description="Дата тестирования"
* ),
* @OA\Property(
* property="questionnaire_title",
* type="string",
* example="Анкета 1",
* description="Название анкеты"
* ),
*)
*
* @OA\Schema(
* schema="UserQuestionnaireExample",
* type="array",
* @OA\Items(
* type="object",
* ref="#/components/schemas/UserQuestionnaire",
* ),
*)
*
* @OA\Schema(
* schema="UserQuestionnaireArrExample",
* type="array",
* example={
* {"uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", "score": 11, "status": 2, "percent_correct_answers": 0.25, "testing_date": "2022-04-03 09:23:45", "questionnaire_title": "Тест 2"},
* {"uuid": "gcjs77d9-vtyd-02jh-9467-dc8fbb6s6jdb", "score": 20, "status": 2, "percent_correct_answers": 0.85, "testing_date": "2022-03-17 11:14:22", "questionnaire_title": "Тест 1"},
* },
* @OA\Items(
* type="object",
* @OA\Property(
* property="uuid",
* type="string",
* ),
* @OA\Property(
* property="score",
* type="integer",
* ),
* @OA\Property(
* property="status",
* type="integer",
* ),
* @OA\Property(
* property="percent_correct_answers",
* type="float",
* ),
* @OA\Property(
* property="testing_date",
* type="string",
* ),
* @OA\Property(
* property="questionnaire_title",
* type="string",
* ),
* ),
*)
*
*/
class UserQuestionnaire extends \common\models\UserQuestionnaire
{
}

View File

@ -98,5 +98,13 @@ namespace frontend\modules\api\models;
*/ */
class UserResponse extends \common\models\UserResponse class UserResponse extends \common\models\UserResponse
{ {
public function fields(): array
{
return [
'user_id',
'question_id',
'response_body',
'user_questionnaire_uuid',
];
}
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace frontend\modules\api\models; namespace frontend\modules\api\models\company;
/** /**
* *

View File

@ -0,0 +1,106 @@
<?php
namespace frontend\modules\api\models\company\dto;
/**
*
* @OA\Schema(
* schema="CompanyPersonnelDto",
* @OA\Property(
* property="userId",
* type="int",
* example=95,
* description="Идентификатор пользователя"
* ),
* @OA\Property(
* property="fio",
* type="string",
* example="Кочетков Валерий Александрович",
* description="ФИО пользователя"
* ),
* @OA\Property(
* property="position",
* type="string",
* example="Back end разработчик",
* description="Должность пользователя"
* ),
* @OA\Property(
* property="level",
* type="int",
* example="Middle",
* description="Уровень компетенций"
* ),
* @OA\Property(
* property="projectName",
* type="string",
* example="Проект 1",
* description="Название проекта на котором работает"
* ),
* @OA\Property(
* property="openTaskCount",
* type="int",
* example="5",
* description="Количество открытых задач на проекте"
* ),
* @OA\Property(
* property="hoursWorkedForCurrentMonth",
* type="int",
* example="5",
* description="Количество часов отработанных в текущем месяце"
* ),
*)
*
* @OA\Schema(
* schema="CompanyPersonnelDtoExampleArr",
* type="array",
* example={
* {"userId": 23, "fio": "Кочетков Валерий Александрович", "position": "Back end разработчик", "level": 2, "projectName": "Проект 1", "openTaskCount": 4, "hoursWorkedForCurrentMonth": 30},
* {"userId": 16, "fio": "Шишкина Милана Андреевна", "position": "Back end разработчик", "level": 1, "projectName": "Проект 2", "openTaskCount": 8, "hoursWorkedForCurrentMonth": 15},
* },
* @OA\Items(
* type="object",
* @OA\Property(
* property="userId",
* type="integer",
* ),
* @OA\Property(
* property="fio",
* type="string",
* ),
* @OA\Property(
* property="position",
* type="string",
* ),
* @OA\Property(
* property="level",
* type="integer",
* ),
* @OA\Property(
* property="projectName",
* type="string",
* ),
* @OA\Property(
* property="openTaskCount",
* type="integer",
* ),
* @OA\Property(
* property="hoursWorkedForCurrentMonth",
* type="integer",
* ),
* ),
*)
*
*
*
*/
class CompanyPersonnelDto
{
public $userId;
public $fio;
public $position;
public $level;
public $projectName;
public $openTaskCount;
public $hoursWorkedForCurrentMonth;
}

View File

@ -0,0 +1,30 @@
<?php
namespace frontend\modules\api\models\company\form;
use frontend\modules\api\models\company\Company;
use yii\base\Model;
class CompanyIdForm extends Model
{
public $company_id;
/**
* @return array
*/
public function rules()
{
return [
[['company_id'], 'required'],
[['company_id'], 'exist', 'skipOnError' => false, 'targetClass' => Company::class, 'targetAttribute' => ['company_id' => 'id']],
];
}
/**
* @return string
*/
public function formName(): string
{
return '';
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace frontend\modules\api\models\company\mappers;
use frontend\modules\api\models\company\dto\CompanyPersonnelDto;
use frontend\modules\api\models\project\ProjectUser;
use frontend\modules\api\services\TaskService;
class CompanyPersonnelMapper
{
/**
* @param ProjectUser $projectUser
* @return CompanyPersonnelDto
*/
public static function map(ProjectUser $projectUser): CompanyPersonnelDto
{
$dto = new CompanyPersonnelDto();
$dto->userId = $projectUser->user_id;
$dto->fio = $projectUser->card->fio ?? null;
$dto->position = $projectUser->card->position->name ?? null;
$dto->level = $projectUser->card->level ?? null;
$dto->projectName = $projectUser->project->name;
$dto->openTaskCount = TaskService::getOpenTaskCount($projectUser->user_id, $projectUser->project_id);
$dto->hoursWorkedForCurrentMonth = TaskService::getHoursWorkedForCurrentMonth($projectUser->user_id, $projectUser->project_id);
return $dto;
}
/**
* @param array $projectUsers
* @return array
*/
public static function mapAll(array $projectUsers): array
{
return array_map(function (ProjectUser $projectUser) {
return self::map($projectUser);
}, array_values($projectUsers));
}
}

View File

@ -1,11 +1,10 @@
<?php <?php
namespace frontend\modules\api\models; namespace frontend\modules\api\models\profile;
use backend\modules\card\models\UserCard; use backend\modules\card\models\UserCard;
use common\classes\Debug;
use yii\base\Model; use yii\base\Model;
/** /**

View File

@ -1,9 +1,8 @@
<?php <?php
namespace frontend\modules\api\models; namespace frontend\modules\api\models\profile;
use backend\modules\card\models\UserCardSearch; use frontend\modules\api\services\ProfileService;
use common\services\ProfileService;
class User extends \common\models\User class User extends \common\models\User
{ {

View File

@ -0,0 +1,31 @@
<?php
namespace frontend\modules\api\models\profile\forms;
use frontend\modules\api\models\profile\User;
use yii\base\Model;
class ProfileChangeEmailForm extends Model
{
public $newEmail;
/**
* @return array
*/
public function rules()
{
return [
[['newEmail'], 'string'],
[['newEmail'], 'required'],
[['newEmail'], 'email'],
['newEmail', 'unique', 'targetAttribute' => 'email', 'targetClass' => User::class],
];
}
/**
* @return string
*/
public function formName(): string
{
return '';
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace frontend\modules\api\models\profile\forms;
use yii\base\Model;
class ProfileChangePasswordForm extends Model
{
public $password;
public $newPassword;
/**
* @return array
*/
public function rules()
{
return [
[['password', 'newPassword'], 'string'],
[['password', 'newPassword'], 'required'],
];
}
/**
* @return string
*/
public function formName(): string
{
return '';
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace frontend\modules\api\models\profile\forms;
use yii\base\Model;
class ProfileChangePersonalDataForm extends Model
{
/**
* @var string
*/
public $newUsername;
/**
* @return array
*/
public function rules()
{
return [
[['newUsername'], 'string', 'max' => 255],
[['newUsername'], 'required'],
];
}
/**
* @return string
*/
public function formName(): string
{
return '';
}
}

View File

@ -1,11 +1,11 @@
<?php <?php
namespace frontend\modules\api\models; namespace frontend\modules\api\models\project;
use frontend\modules\api\models\company\Company;
use yii\db\ActiveQuery; use yii\db\ActiveQuery;
use yii\helpers\Url; use yii\helpers\Url;
use yii\web\Link; use yii\web\Link;
use yii\web\Linkable;
/** /**
* *

Some files were not shown because too many files have changed in this diff Show More