Merge pull request #89 from apuc/add_document

Add document
This commit is contained in:
kavalar 2022-03-15 12:54:08 +03:00 committed by GitHub
commit 0031b9cf20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1524 additions and 262 deletions

View File

@ -2,6 +2,8 @@
namespace backend\modules\document\controllers;
use PhpOffice\PhpWord\Exception\CopyFileException;
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
use Yii;
use backend\modules\document\models\Document;
use backend\modules\document\models\DocumentSearch;
@ -10,7 +12,8 @@ use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use common\services\DocumentService;
use common\services\DocumentFileService;
use yii\web\Response;
/**
* DocumentController implements the CRUD actions for Document model.
@ -142,10 +145,15 @@ class DocumentController extends Controller
}
public function actionCreateDocument($id)
/**
* @throws CopyFileException
* @throws NotFoundHttpException
* @throws CreateTemporaryFileException
*/
public function actionCreateDocument($id): Response
{
if(!empty($this->findModel($id)->template->template_file_name)){
$documentService = new DocumentService($id);
$documentService = new DocumentFileService($id);
$documentService->setFields();
$documentService->downloadDocument();
}

View File

@ -4,7 +4,6 @@ namespace backend\modules\questionnaire\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use backend\modules\questionnaire\models\UserQuestionnaire;
/**
* UserQuestionnaireSearch represents the model behind the search form of `backend\modules\questionnaire\models\UserQuestionnaire`.
@ -18,7 +17,7 @@ class UserQuestionnaireSearch extends UserQuestionnaire
{
return [
[['id', 'questionnaire_id', 'user_id', 'score', 'status'], 'integer'],
[['uuid', 'created_at', 'updated_at'], 'safe'],
[['uuid', 'created_at', 'updated_at', 'testing_date'], 'safe'],
[['percent_correct_answers'], 'number'],
];
}
@ -67,6 +66,7 @@ class UserQuestionnaireSearch extends UserQuestionnaire
'score' => $this->score,
'status' => $this->status,
'percent_correct_answers' => $this->percent_correct_answers,
'testing_date' => $this->testing_date,
]);
$query->andFilterWhere(['like', 'uuid', $this->uuid]);

View File

@ -33,6 +33,8 @@ use yii\widgets\ActiveForm;
<?php // echo $form->field($model, 'percent_correct_answers') ?>
<?php // echo $form->field($model, 'testing_date') ?>
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>

View File

@ -53,6 +53,7 @@ $this->params['breadcrumbs'][] = $this->title;
],
'created_at',
'updated_at',
'testing_date',
['class' => 'yii\grid\ActionColumn'],
],

View File

@ -77,6 +77,7 @@ YiiAsset::register($this);
],
'created_at',
'updated_at',
'testing_date',
],
]) ?>

View File

@ -110,13 +110,4 @@ class Document extends \yii\db\ActiveRecord
{
return $this->hasMany(DocumentFieldValue::className(), ['document_id' => 'id']);
}
public static function getDocument($document_id)
{
return self::find()
->joinWith(['documentFieldValues.field'])
->where(['document.id' => $document_id])
->asArray()
->all();
}
}

View File

@ -123,4 +123,10 @@ class Template extends \yii\db\ActiveRecord
{
return $this->title;
}
public function getFields()
{
return $this->hasMany(DocumentField::className(), ['id' => 'field_id'])
->via('templateDocumentFields');
}
}

View File

@ -63,7 +63,7 @@ class UserQuestionnaire extends ActiveRecord
[['questionnaire_id', 'user_id', 'status'], 'required'],
[['questionnaire_id', 'user_id', 'score', 'status'], 'integer'],
[['percent_correct_answers'], 'number'],
[['created_at', 'updated_at'], 'safe'],
[['created_at', 'updated_at', 'testing_date'], 'safe'],
[['uuid'], 'string', 'max' => 36],
[['uuid'], 'unique'],
[['questionnaire_id'], 'exist', 'skipOnError' => true, 'targetClass' => Questionnaire::className(), 'targetAttribute' => ['questionnaire_id' => 'id']],
@ -74,8 +74,7 @@ class UserQuestionnaire extends ActiveRecord
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if (empty($this->uuid))
{
if (empty($this->uuid)) {
$this->uuid = UUIDHelper::v4();
}
return true;
@ -98,6 +97,7 @@ class UserQuestionnaire extends ActiveRecord
'status' => 'Статус',
'created_at' => 'Дата создания',
'updated_at' => 'Дата обновления',
'testing_date' => 'Дата тестирования',
'percent_correct_answers' => 'Процент правильных ответов',
];
}
@ -178,8 +178,18 @@ class UserQuestionnaire extends ActiveRecord
public static function findActiveUserQuestionnaires($user_id): array
{
return self::find()->where(['user_id' => $user_id])
->andWhere(['status' => '1'])
$models = self::find()
->where(['user_id' => $user_id])
->andWhere(['user_questionnaire.status' => '1'])
->all();
$modelsArr = array();
foreach ($models as $model) {
$modelsArr[] = array_merge($model->toArray(), [
'questionnaire_title' => $model->getQuestionnaireTitle()
]);
}
return $modelsArr;
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace common\services;
use common\models\Document;
use PhpOffice\PhpWord\Exception\CopyFileException;
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
use PhpOffice\PhpWord\TemplateProcessor;
use Yii;
class DocumentFileService
{
private $model;
private $document;
private $file_title;
private $documentFieldValuesArr;
/**
* @throws CopyFileException
* @throws CreateTemporaryFileException
*/
public function __construct($modelID)
{
$this->model = Document::findOne($modelID);
$this->initDocument();
}
/**
* @throws CopyFileException
* @throws CreateTemporaryFileException
*/
private function initDocument()
{
$this->file_title = $this->model->title . '.docx';
$template_title = $this->model->template->template_file_name;
$this->document = new TemplateProcessor(
Yii::getAlias('@templates') . "/$template_title");
$this->documentFieldValuesArr = $this->model->documentFieldValues;
}
public function setFields()
{
foreach ($this->documentFieldValuesArr as $docFieldValue) {
$this->document->setValue(
$docFieldValue->field->field_template,
$docFieldValue->value
);
}
}
public function downloadDocument()
{
$this->document->saveAs($this->file_title);
// Имя скачиваемого файла
$downloadFile = $this->file_title;
// Контент-тип означающий скачивание
header("Content-Type: application/octet-stream");
// Размер в байтах
header("Accept-Ranges: bytes");
// Размер файла
header("Content-Length: ".filesize($downloadFile));
// Расположение скачиваемого файла
header("Content-Disposition: attachment; filename=".$downloadFile);
// Прочитать файл
readfile($downloadFile);
unlink($this->file_title);
}
}

View File

@ -2,73 +2,27 @@
namespace common\services;
use common\models\Document;
use PhpOffice\PhpWord\Exception\CopyFileException;
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
use PhpOffice\PhpWord\TemplateProcessor;
use Yii;
class DocumentService
{
private $model;
private $document;
private $file_title;
private $documentFieldValuesArr;
/**
* @throws CopyFileException
* @throws CreateTemporaryFileException
*/
public function __construct($modelID)
public static function getDocumentList($document_type): array
{
$this->model = Document::findOne($modelID);
$this->initDocument();
if (!empty($document_type)) {
return Document::find()->joinWith('template')
->where(['document_type' => $document_type])->asArray()->all();
}
else {
return Document::find()->asArray()->all();
}
}
/**
* @throws CopyFileException
* @throws CreateTemporaryFileException
*/
private function initDocument()
public static function getDocument($document_id)
{
$this->file_title = $this->model->title . '.docx';
return Document::find()
->joinWith(['documentFieldValues.field'])
->where(['document.id' => $document_id])
->asArray()->all();
$template_title = $this->model->template->template_file_name;
$this->document = new TemplateProcessor(
Yii::getAlias('@templates') . "/$template_title");
$this->documentFieldValuesArr = $this->model->documentFieldValues;
}
public function setFields()
{
foreach ($this->documentFieldValuesArr as $docFieldValue) {
$this->document->setValue(
$docFieldValue->field->field_template,
$docFieldValue->value
);
}
}
public function downloadDocument()
{
$this->document->saveAs($this->file_title);
// Имя скачиваемого файла
$downloadFile = $this->file_title;
// Контент-тип означающий скачивание
header("Content-Type: application/octet-stream");
// Размер в байтах
header("Accept-Ranges: bytes");
// Размер файла
header("Content-Length: ".filesize($downloadFile));
// Расположение скачиваемого файла
header("Content-Disposition: attachment; filename=".$downloadFile);
// Прочитать файл
readfile($downloadFile);
unlink($this->file_title);
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace common\services;
use common\models\UserCard;
class ManagerService
{
public static function getManagerList()
{
return UserCard::find()->select(['fio','manager.id' , 'email'])
->joinWith('manager')->where(['NOT',['manager.user_card_id' => null]])->all();
}
public static function getManager($manager_id)
{
return UserCard::find()
->select(['manager.id', 'fio', 'email', 'photo', 'gender'])
->joinWith([
'manager' => function ($query) { $query->select(['id']); }
])
->where(['manager.id' => $manager_id])
->asArray()
->one();
}
public static function getManagerEmployeesList($manager_id)
{
return UserCard::find()
->select(['user_card.id', 'user_card.fio', 'user_card.email'])
->joinWith('managerEmployee')
->where(['manager_employee.manager_id' => $manager_id])
->all();
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace common\services;
use common\models\Task;
class TaskService
{
public static function createTask($taskParams)
{
$task = new Task();
$task->load($taskParams, '');
$task->save();
return $task;
}
public static function getTask($task_id): ?Task
{
return Task::findOne($task_id);
}
public static function getTaskList($task_id): array
{
return Task::find()->asArray()->all();
}
public static function getTaskListByProject($project_id): array
{
return Task::find()->where(['project_id' => $project_id])->asArray()->all();
}
public static function updateTask($task_params): ?Task
{
$modelTask = Task::findOne($task_params['task_id']);
$modelTask->load($task_params, '');
$modelTask->save();
return $modelTask;
}
public static function taskExists($task_id): bool
{
return Task::find()->where(['id' => $task_id])->exists();
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace common\services;
use common\models\Template;
class TemplateService
{
public static function getTemplateList($document_type = null): array
{
if (!empty($document_type)) {
return Template::find()->where(['document_type' => $document_type])->asArray()->all();
}
else {
return Template::find()->asArray()->all();
}
}
public static function getTemplateWithFields($template_id): array
{
return Template::find()
// ->select('title')
->joinWith('templateDocumentFields.field')
// ->with([
// 'fields' => function ($query) { $query->select(['id', 'title', 'field_template']); }
// ])
->where(['template.id' => $template_id])
->asArray()
->one();
}
public static function getTemplate($template_id): array
{
return Template::find()->where(['template.id' => $template_id])
->asArray()
->one();
}
}

View File

@ -0,0 +1,40 @@
<?php
use yii\db\Migration;
/**
* Class m220214_143240_add_column_testing_date_to_user_questionnaire_table
*/
class m220214_143240_add_column_testing_date_to_user_questionnaire_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('user_questionnaire', 'testing_date', $this->dateTime()->defaultValue(null));
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('user_questionnaire', 'testing_date');
}
/*
// Use up()/down() to run migration code without a transaction.
public function up()
{
}
public function down()
{
echo "m220214_143240_add_column_testing_date_to_user_questionnaire_table cannot be reverted.\n";
return false;
}
*/
}

329
docs/api/document.md Normal file
View File

@ -0,0 +1,329 @@
# Документы
## Методы
<table>
<tr>
<th>
Метод
</th>
<th>
Описание
</th>
</tr>
<tr>
<td>
get-document-list
</td>
<td>
Возвращает список документов
</td>
</tr>
<tr>
<td>
get-document
</td>
<td>
Возвращает документ
</td>
</tr>
<tr>
<td>
create-document
</td>
<td>
Создание документа
</td>
</tr>
</table>
## Список документов
`https://guild.craft-group.xyz/api/document/get-document-list?document_type=1`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
document_type
</td>
<td>
Тип документа. Возможные значения: 1 - Акт; 2 - Договор
</td>
</tr>
</table>
<p>
Без передачи параметра возвращает массив объектов <b>Документ</b> . С параметром <b>document_type</b>,
метод возвращает объекты <b>Документ</b> определённого типа(<b>1 - Акт; 2 - Договор</b>).
При отсутствии документов возвращает ошибку: "Not Found".
</p>
<p>
Возвращает <b>массив</b> объектов <b>Документ</b>. <br>
Каждый объект <b>Документ</b> имеет такой вид:
</p>
```json5
[
{
"id": "88",
"title": "Act2",
"created_at": "2022-01-12 16:39:41",
"updated_at": "2022-01-12 16:39:41",
"template_id": "94",
"manager_id": "5",
"template": {
"id": "94",
"title": "Акт",
"created_at": "2022-01-11 11:47:11",
"updated_at": null,
"template_file_name": null,
"document_type": "2"
}
},
'...'
]
```
<p>
Пример ошибки:
</p>
```json5
{
"name": "Not Found",
"message": "Documents not found",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}
```
## Получить документ
`https://guild.craft-group.xyz/api/document/get-document?document_id=88`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
document_id
</td>
<td>
Id документа
</td>
</tr>
</table>
<p>
Возвращает объект <b>Документ</b>. <br>
Каждый объект <b>Документ</b> имеет такой вид:
</p>
```json5
[
{
"id": "88",
"title": "Act2",
"created_at": "2022-01-12 16:39:41",
"updated_at": "2022-01-12 16:39:41",
"template_id": "94",
"manager_id": "5",
"documentFieldValues": [
{
"id": "105",
"field_id": "43",
"document_id": "88",
"value": "№ документа111",
"field": {
"id": "43",
"title": "№ документа",
"field_template": "№ dokumenta"
}
},
{
"id": "106",
"field_id": "44",
"document_id": "88",
"value": "от111",
"field": {
"id": "44",
"title": "от",
"field_template": "ot"
}
},
{
"id": "107",
"field_id": "45",
"document_id": "88",
"value": "Сумма с НДС111",
"field": {
"id": "45",
"title": "Сумма с НДС",
"field_template": "Summa s NDS"
}
},
{
"id": "108",
"field_id": "46",
"document_id": "88",
"value": "НДС111",
"field": {
"id": "46",
"title": "НДС",
"field_template": "NDS"
}
},
{
"id": "109",
"field_id": "47",
"document_id": "88",
"value": "Основание111",
"field": {
"id": "47",
"title": "Основание",
"field_template": "Osnovaniye"
}
}
]
}
]
```
<p>
Пример ошибки:
</p>
```json5
{
"name": "Not Found",
"message": "There is no such document",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}
```
## Создать документ
`https://guild.craft-group.xyz/api/document/create-document`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
title
</td>
<td>
Название документа
</td>
</tr>
<tr>
<td>
template_id
</td>
<td>
Id шаблона
</td>
</tr>
<tr>
<td>
manager_id
</td>
<td>
Id менеджера
</td>
</tr>
<tr>
<td>
field_id
</td>
<td>
Id поля
</td>
</tr>
<tr>
<td>
value
</td>
<td>
Значение поля
</td>
</tr>
</table>
<p>
Создаёт <b>Документ</b>. Требует передачи <b>POST</b> запроса с соответствующими
параметрами документа и полей документа
</p>
<p>
Пример передаваемого объекта:
</p>
```json5
{
"title": "Act64",
"template_id": "94",
"manager_id": "5",
"documentFieldValues": [
{
"field_id": "43",
"value": "№ документа111"
},
{
"field_id": "44",
"value": "от111"
},
{
"field_id": "45",
"value": "Сумма с НДС111"
},
{
"field_id": "46",
"value": "НДС111"
},
{
"field_id": "47",
"value": "Основание111"
}
]
}
```
<p>
В случае указания не верных параметров буде возвращена соответствующая ошибка. Пример ошибки:
</p>
```json5
{
"name": "Bad Request",
"message": "{\"template_id\":[\"\Ш\а\б\л\о\н cannot be blank.\"]}",
"code": 0,
"status": 400,
"type": "yii\\web\\BadRequestHttpException"
}
```

View File

@ -27,7 +27,7 @@
</tr>
<tr>
<td>
limit
get-document-list
</td>
<td>
Количество профилей, которое вернет сервер при запросе.
@ -256,7 +256,7 @@
Пример запроса:
</p>
`https://guild.craft-group.xyz/api/reports/index?fromDate=2021-08-01&toDate=2021-08-31&user_id=2limit=3&offset=2`
`https://guild.craft-group.xyz/api/reports/index?fromDate=2021-08-01&toDate=2021-08-31&user_id=2&limit=3&offset=2`
### Один отчет
`https://guild.craft-group.xyz/api/reports/{id}`
@ -291,6 +291,96 @@
`https://guild.craft-group.xyz/api/reports/13`
### Отчёт по дате
`https://guild.craft-group.xyz/api/reports/find-by-date`
<p>
Для получения отчета необходимо отправить <b>GET</b> запрос на URL https://guild.craft-group.xyz/api/reports/find-by-date
</p>
<p>
Требуемые параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
user_card_id*
</td>
<td>
ID профиля пользователя
</td>
</tr>
<tr>
<td>
date*
</td>
<td>
Дата в формате: Y-m-d
</td>
</tr>
</table>
<p>
Пример запроса :
</p>
`https://guild.craft-group.xyz/api/reports/find-by-date?user_card_id=17&date=2022-02-14`
<p>
Пример ответа:
</p>
```json5
[
{
"id": "1",
"created_at": "2022-02-14",
"today": null,
"difficulties": "",
"tomorrow": "",
"status": null,
"user_card_id": "17",
"task": [
{
"id": "1",
"report_id": "1",
"task": "dfghjkl",
"hours_spent": "2",
"created_at": "1644842433",
"status": "1",
"minutes_spent": "4"
}
]
},
{
"id": "2",
"created_at": "2022-02-14",
"today": "dxvxv",
"difficulties": "сложности возникли",
"tomorrow": "завтра",
"status": null,
"user_card_id": "17",
"task": [
{
"id": "2",
"report_id": "2",
"task": "54651513",
"hours_spent": "4",
"created_at": "1644842630",
"status": "1",
"minutes_spent": "2"
}
]
}
]
```
### Создать отчет
`https://guild.craft-group.xyz/api/reports/create`

141
docs/api/manager.md Normal file
View File

@ -0,0 +1,141 @@
# Менеджеры
## Методы
<table>
<tr>
<th>
Метод
</th>
<th>
Описание
</th>
</tr>
<tr>
<td>
get-manager-list
</td>
<td>
Возвращает список менеджеров
</td>
</tr>
<tr>
<td>
get-manager-employees-list
</td>
<td>
Возвращает список сотрудников менеджера
</td>
</tr>
<tr>
<td>
get-manager
</td>
<td>
Возвращает менеджера
</td>
</tr>
</table>
## Список менеджеров
`https://guild.craft-group.xyz/api/manager/get-manager-list`
<p>
Возвращает <b>массив</b> объектов <b>Менеджер</b>. <br>
Каждый объект <b>Менеджер</b> имеет такой вид:
</p>
```json5
[
{
"fio": "Иванов Иван Иванович",
"id": 5,
"email": "testmail@mail.com"
},
'...'
]
```
## Получить менеджера
`https://guild.craft-group.xyz/api/manager/get-manager?manager_id=5`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
manager_id
</td>
<td>
Id менеджера
</td>
</tr>
</table>
<p>
Возвращает объект <b>Менеджер</b>. <br>
Каждый объект <b>Менеджер</b> имеет такой вид:
</p>
```json5
{
"id": "5",
"fio": "Иванов Иван Иванович",
"email": "testmail@mail.com",
"photo": "",
"gender": "0",
"manager": {
"id": "3"
}
}
```
## Получить сотрудников менеджера
`https://guild.craft-group.xyz/api/manager/get-manager-employees-list?manager_id=5`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
manager_id
</td>
<td>
Id менеджера
</td>
</tr>
</table>
<p>
Возвращает массив объектов <b>Профиль</b> сотрудников, что закреплены за менеджером. <br>
Каждый объект <b>Профиль</b> имеет такой вид:
</p>
```json5
[
{
"id": 2,
"fio": "тусыавт2",
"email": "jnjhbdhvf@mail.com"
},
'...'
]
```

321
docs/api/task.md Normal file
View File

@ -0,0 +1,321 @@
# Задачи
## Методы
<table>
<tr>
<th>
Метод
</th>
<th>
Описание
</th>
</tr>
<tr>
<td>
get-task-list
</td>
<td>
Возвращает список задач
</td>
</tr>
<tr>
<td>
get-task
</td>
<td>
Возвращает задачу
</td>
</tr>
<tr>
<td>
create-task
</td>
<td>
Создаёт задачу
</td>
</tr>
<tr>
<td>
update
</td>
<td>
Обновить задачу
</td>
</tr>
</table>
## Список задач
`https://guild.craft-group.xyz/api/task/get-task-list?project_id=1`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
project_id
</td>
<td>
Id проекта
</td>
</tr>
</table>
<p>
Без передачи параметра возвращает массив объектов <b>Задача</b> . С параметром <b>project_id</b>,
метод возвращает объекты <b>Задача</b> определённого проекта.
</p>
<p>
Возвращает <b>массив</b> объектов <b>Задача</b>. <br>
Каждый объект <b>Задача</b> имеет такой вид:
</p>
```json5
[
{
"id": "6",
"project_id": "74",
"title": "Название задачи",
"status": "1",
"created_at": "2021-12-20 16:29:39",
"updated_at": "2021-12-20 17:35:04",
"description": "Описание задачи",
"card_id_creator": "1",
"card_id": "3"
},
'...'
]
```
## Получить документ
`https://guild.craft-group.xyz/api/task/get-task?task_id=15`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
task_id
</td>
<td>
Id задачи
</td>
</tr>
</table>
<p>
Возвращает объект <b>Задача</b>. <br>
Каждый объект <b>Задача</b> имеет такой вид:
</p>
```json5
{
"id": 15,
"project_id": 74,
"title": "4324238888",
"status": 1,
"created_at": "2022-01-05 17:37:37",
"updated_at": "2022-01-05 17:46:10",
"description": "888",
"card_id_creator": 1,
"card_id": null
}
```
<p>
Пример ошибки:
</p>
```json5
{
"name": "Not Found",
"message": "The task does not exist",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}
```
## Создать документ
`https://guild.craft-group.xyz/api/document/create-document`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
title
</td>
<td>
Название задачи
</td>
</tr>
<tr>
<td>
project_id
</td>
<td>
Id проекта
</td>
</tr>
<tr>
<td>
status
</td>
<td>
статус задачи
</td>
</tr>
<tr>
<td>
card_id_creator
</td>
<td>
Id профиля создателя
</td>
</tr>
<tr>
<td>
card_id
</td>
<td>
Id профиля наблюдателя(не обязательный параметр)
</td>
</tr>
<tr>
<td>
description
</td>
<td>
Описание
</td>
</tr>
</table>
<p>
Создаёт <b>Задача</b>. Требует передачи <b>POST</b> запроса с соответствующими
параметрами
</p>
<p>
В случае указания не верных параметров буде возвращена соответствующая ошибка. Пример ошибки:
</p>
```json5
{
"name": "Internal Server Error",
"message": "{\"project_id\":[\"\П\р\о\е\к\т is invalid.\"]}",
"code": 0,
"status": 500,
"type": "yii\\web\\ServerErrorHttpException"
}
```
## Обновить документ
`https://guild.craft-group.xyz/api/task/update`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
title
</td>
<td>
Название задачи
</td>
</tr>
<tr>
<td>
project_id
</td>
<td>
Id проекта
</td>
</tr>
<tr>
<td>
status
</td>
<td>
статус задачи
</td>
</tr>
<tr>
<td>
card_id_creator
</td>
<td>
Id профиля создателя
</td>
</tr>
<tr>
<td>
card_id
</td>
<td>
Id профиля наблюдателя(не обязательный параметр)
</td>
</tr>
<tr>
<td>
description
</td>
<td>
Описание
</td>
</tr>
</table>
<p>
Обновляет объект <b>Задача</b>. Требует передачи <b>POST</b> запроса с соответствующими
параметрами
</p>
<p>
В случае указания не верных параметров буде возвращена соответствующая ошибка. Пример ошибки:
</p>
```json5
{
"name": "Not Found",
"message": "The task does not exist",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}
```

219
docs/api/template.md Normal file
View File

@ -0,0 +1,219 @@
# Шаблоны
## Методы
<table>
<tr>
<th>
Метод
</th>
<th>
Описание
</th>
</tr>
<tr>
<td>
get-template-list
</td>
<td>
Возвращает список шаблонов
</td>
</tr>
<tr>
<td>
get-template-fields
</td>
<td>
Возвращает поля шаблона
</td>
</tr>
<tr>
<td>
get-template
</td>
<td>
Возвращает шаблон
</td>
</tr>
</table>
## Список шаблонов
`https://guild.craft-group.xyz/api/template/get-template-list?document_type=1`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
document_type
</td>
<td>
Тип документа. Возможные значения: 1 - Акт; 2 - Договор
</td>
</tr>
</table>
<p>
Без передачи параметра возвращает массив объектов <b>Шаблон</b> . С параметром <b>document_type</b>,
метод возвращает объекты <b>Шаблон</b> определённого типа(<b>1 - Акт; 2 - Договор</b>).
</p>
<p>
Возвращает <b>массив</b> объектов <b>Шаблон</b>. <br>
Каждый объект <b>Шаблон</b> имеет такой вид:
</p>
```json5
[
{
"id": "94",
"title": "Акт",
"created_at": "2022-01-11 11:47:11",
"updated_at": null,
"template_file_name": null,
"document_type": "2"
},
'...'
]
```
## Получить шаблон
`https://guild.craft-group.xyz/api/template/get-template?template_id=94`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
template_id
</td>
<td>
Id шаблона
</td>
</tr>
</table>
<p>
Возвращает объект <b>Шаблон</b>. <br>
Каждый объект <b>Шаблон</b> имеет такой вид:
</p>
```json5
{
"id": "94",
"title": "Акт",
"created_at": "2022-01-11 11:47:11",
"updated_at": null,
"template_file_name": null,
"document_type": "2"
}
```
## Получить поля шаблона
`https://guild.craft-group.xyz/api/template/get-template-fields?template_id=94`
<p>
Параметры:
</p>
<table>
<tr>
<th>
Параметры
</th>
<th>
Значение
</th>
</tr>
<tr>
<td>
template_id
</td>
<td>
Id шаблона
</td>
</tr>
</table>
<p>
Возвращает объект <b>Шаблон</b>. <br>
Каждый объект <b>Шаблон</b> имеет такой вид:
</p>
```json5
{
"id": "94",
"title": "Акт",
"created_at": "2022-01-11 11:47:11",
"updated_at": null,
"template_file_name": null,
"document_type": "2",
"templateDocumentFields": [
{
"id": "159",
"template_id": "94",
"field_id": "43",
"field": {
"id": "43",
"title": "№ документа",
"field_template": "№ dokumenta"
}
},
{
"id": "160",
"template_id": "94",
"field_id": "44",
"field": {
"id": "44",
"title": "от",
"field_template": "ot"
}
},
{
"id": "161",
"template_id": "94",
"field_id": "45",
"field": {
"id": "45",
"title": "Сумма с НДС",
"field_template": "Summa s NDS"
}
},
{
"id": "162",
"template_id": "94",
"field_id": "46",
"field": {
"id": "46",
"title": "НДС",
"field_template": "NDS"
}
},
{
"id": "163",
"template_id": "94",
"field_id": "47",
"field": {
"id": "47",
"title": "Основание",
"field_template": "Osnovaniye"
}
}
]
}
```

View File

@ -4,14 +4,10 @@ namespace frontend\modules\api\controllers;
use common\models\Document;
use common\models\DocumentFieldValue;
use common\models\Template;
use common\models\TemplateDocumentField;
use Exception;
use common\services\DocumentService;
use Yii;
use yii\filters\auth\HttpBearerAuth;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\rest\Controller;
use yii\web\ServerErrorHttpException;
class DocumentController extends ApiController
@ -20,33 +16,37 @@ class DocumentController extends ApiController
public function verbs(): array
{
return [
// 'get-task' => ['get'],
'get-document-list' => ['get'],
'get-document' => ['get'],
'create-document' => ['post'],
// 'update-task' => ['put', 'patch'],
];
}
public function actionGetDocumentList(): array
/**
* @throws NotFoundHttpException
*/
public function actionGetDocumentList($document_type = null): array
{
$documents = Document::find()->select(['id','title', 'manager_id'])->all();
$documents = DocumentService::getDocumentList($document_type);
if(empty($documents)) {
throw new NotFoundHttpException('Documents are not assigned');
throw new NotFoundHttpException('Documents not found');
}
return $documents;
}
public function actionGetDocument(): array
/**
* @throws NotFoundHttpException
*/
public function actionGetDocument($document_id): array
{
$document_id = Yii::$app->request->get('document_id');
if(empty($document_id) or !is_numeric($document_id))
{
throw new NotFoundHttpException('Incorrect document ID');
}
$document = Document::getDocument($document_id);
$document = DocumentService::getDocument($document_id);
if(empty($document)) {
throw new NotFoundHttpException('There is no such document');
@ -58,10 +58,7 @@ class DocumentController extends ApiController
public function actionCreateDocument()
{
$document = Yii::$app->getRequest()->getBodyParams();
$documentFieldValues = Yii::$app->getRequest()->getBodyParams()['documentFieldValues'];
$tmp = TemplateDocumentField::find()->select('field_id')
->where(['template_id' => 94])->asArray()->all();
$documentFieldValues = $document['documentFieldValues'];
$modelDocument = new Document();
if ($modelDocument->load($document, '') && $modelDocument->save()) {
@ -79,7 +76,7 @@ class DocumentController extends ApiController
}
Yii::$app->getResponse()->setStatusCode(201);
return Document::getDocument($modelDocument->id);
return DocumentService::getDocument($modelDocument->id);
}
private function createDocimentFields($documentFieldValues , $document_id, $template_id)

View File

@ -2,28 +2,12 @@
namespace frontend\modules\api\controllers;
use common\models\ManagerEmployee;
use common\models\User;
use common\models\UserCard;
use Yii;
use yii\filters\auth\HttpBearerAuth;
use yii\helpers\ArrayHelper;
use common\services\ManagerService;
use yii\web\NotFoundHttpException;
use yii\rest\Controller;
class ManagerController extends Controller
class ManagerController extends ApiController
{
public function behaviors(): array
{
$behaviors = parent::behaviors();
$behaviors['authenticator']['authMethods'] = [
HttpBearerAuth::className(),
];
return $behaviors;
}
public function verbs(): array
{
return [
@ -33,10 +17,12 @@ class ManagerController extends Controller
];
}
/**
* @throws NotFoundHttpException
*/
public function actionGetManagerList(): array
{
$managers = UserCard::find()->select(['fio','manager.id' , 'email'])
->joinWith('manager')->where(['NOT',['manager.user_card_id' => null]])->all();
$managers = ManagerService::getManagerList();
if(empty($managers)) {
throw new NotFoundHttpException('Managers are not assigned');
@ -48,43 +34,33 @@ class ManagerController extends Controller
/**
* @throws NotFoundHttpException
*/
public function actionGetEmployeesManager()
public function actionGetManagerEmployeesList($manager_id): array
{
$manager_id = Yii::$app->request->get('manager_id');
if(empty($manager_id) or !is_numeric($manager_id))
{
throw new NotFoundHttpException('Incorrect manager ID');
}
$users_list = UserCard::find()
->select(['manager_employee.id', 'user_card.fio', 'user_card.email'])
->joinWith('managerEmployee')
->where(['manager_employee.manager_id' => $manager_id])
->all();
$managerEmployeesList = ManagerService::getManagerEmployeesList($manager_id);
if(empty($users_list)) {
if(empty($managerEmployeesList)) {
throw new NotFoundHttpException('Managers are not assigned or employees are not assigned to him');
}
return $users_list;
return $managerEmployeesList;
}
/**
* @throws NotFoundHttpException
*/
public function actionGetManager(): array
public function actionGetManager($manager_id): array
{
$manager_id = Yii::$app->request->get('manager_id');
if(empty($manager_id) or !is_numeric($manager_id))
{
throw new NotFoundHttpException('Incorrect manager ID');
}
$manager = UserCard::find()
->select(['manager.id', 'fio', 'email', 'photo', 'gender'])
->joinWith('manager')->where(['manager.id' => $manager_id])
->all();
$manager = ManagerService::getManager($manager_id);
if(empty($manager)) {
throw new NotFoundHttpException('There is no such manager');

View File

@ -69,6 +69,27 @@ class ReportsController extends ApiController
return array_merge($report->toArray(), ['tasks' => $report->_task]);
}
/**
* @throws NotFoundHttpException
*/
public function actionFindByDate(): array
{
$reportsModel = new ReportSearchForm();
$params = Yii::$app->request->get();
if(!isset($params['user_card_id']) or !isset($params['date'])){
throw new NotFoundHttpException('Required parameter are missing!');
}
$reportsModel->attributes = $params;
$reportsModel->byDate = true;
if(!$reportsModel->validate()){
return $reportsModel->errors;
}
return $reportsModel->byParams();
}
public function actionCreate()
{
$params = Yii::$app->request->post();

View File

@ -3,27 +3,14 @@
namespace frontend\modules\api\controllers;
use common\models\Task;
use common\services\TaskService;
use Yii;
use yii\base\InvalidConfigException;
use yii\filters\auth\HttpBearerAuth;
use yii\rest\Controller;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
use yii\web\ServerErrorHttpException;
class TaskController extends Controller
class TaskController extends ApiController
{
public function behaviors(): array
{
$behaviors = parent::behaviors();
$behaviors['authenticator']['authMethods'] = [
HttpBearerAuth::className(),
];
return $behaviors;
}
public function verbs(): array
{
return [
@ -37,113 +24,79 @@ class TaskController extends Controller
/**
* @throws InvalidConfigException
* @throws ServerErrorHttpException
* @throws NotFoundHttpException
*/
public function actionUpdate(): ?Task
{
$model = $this->findModelTask(Yii::$app->request->post('task_id'));
if(empty($model)) {
throw new NotFoundHttpException('The task does not exist');
}
$model->load(Yii::$app->request->getBodyParams(), '');
if ($model->save() === false && !$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to update the object for unknown reason.');
}
return $model;
}
/**
* @throws InvalidConfigException
* @throws BadRequestHttpException
* @throws ServerErrorHttpException
*/
public function actionCreateTask(): Task
{
$task = Yii::$app->getRequest()->getBodyParams();
$model = new Task();
$model->load($task, '');
$this->validateTaskModel($model);
$this->saveModel($model);
return $model;
$taskModel = TaskService::createTask(Yii::$app->getRequest()->getBodyParams());
if ($taskModel->errors) {
throw new ServerErrorHttpException(json_encode($taskModel->errors));
}
return $taskModel;
}
/**
* @throws ServerErrorHttpException
* @throws NotFoundHttpException
*/
protected function saveModel($model)
public function actionGetTaskList($project_id = null): array
{
if ($model->save()) {
$task = Yii::$app->getResponse();
$task->setStatusCode(201);
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
}
}
/**
* @throws BadRequestHttpException
*/
protected function validateTaskModel($model)
$tasks = array();
if ($project_id)
{
if(!$model->validate()) {
throw new BadRequestHttpException(json_encode($model->errors));
}
if (empty($model->project_id)or empty($model->status)
or empty($model->description) or empty($model->title) or empty($model->card_id_creator)) {
throw new BadRequestHttpException(json_encode($model->errors));
}
}
public function actionGetTaskList(): array
{
$project_id = Yii::$app->request->get('project_id');
if(empty($project_id) or !is_numeric($project_id))
{
throw new NotFoundHttpException('Incorrect project ID');
}
$tasks = $this->findModelsById($project_id);
$tasks = TaskService::getTaskListByProject($project_id);
}
else
{
$tasks = TaskService::getTaskList($project_id);
}
if(empty($tasks)) {
throw new NotFoundHttpException('The project does not exist or there are no tasks for it');
}
return $tasks;
}
public function actionGetTask(): Task
/**
* @throws NotFoundHttpException
*/
public function actionGetTask($task_id): Task
{
$task_id = Yii::$app->request->get('task_id');
if(empty($task_id) or !is_numeric($task_id))
{
throw new NotFoundHttpException('Incorrect task ID');
}
$task = $this->findModelTask($task_id);
$task = TaskService::getTask($task_id);
if(empty($task)) {
throw new NotFoundHttpException('The task does not exist');
}
return $task;
}
private function findModelTask($task_id): ?Task
/**
* @throws InvalidConfigException
* @throws ServerErrorHttpException
* @throws NotFoundHttpException
*/
public function actionUpdate(): ?Task
{
return Task::findOne($task_id);
$params = Yii::$app->request->getBodyParams();
if (empty ($params['task_id']) or !TaskService::taskExists($params['task_id']))
{
throw new NotFoundHttpException('The task does not exist');
}
private function findModelsById($project_id): array
{
return Task::find()->where(['project_id' => $project_id])->all();
$modelTask = TaskService::updateTask($params);
if (!empty($modelTask->hasErrors())) {
throw new ServerErrorHttpException(json_encode('Bad params'));
}
return $modelTask;
}
}

View File

@ -2,14 +2,8 @@
namespace frontend\modules\api\controllers;
use common\models\Document;
use common\models\Template;
use Yii;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\ContentNegotiator;
use common\services\TemplateService;
use yii\web\NotFoundHttpException;
use yii\web\Response;
class TemplateController extends ApiController
{
@ -19,44 +13,57 @@ class TemplateController extends ApiController
return [
'get-template-list' => ['get'],
'get-template-fields' => ['get'],
'get-template' => ['get'],
];
}
public function actionGetTemplateList(): array
/**
* @throws NotFoundHttpException
*/
public function actionGetTemplateList($document_type = null): array
{
$document_type = Yii::$app->request->get('document_type');
$templateList = TemplateService::getTemplateList($document_type);
if (!empty($document_type)) {
$template = Template::find()->where(['document_type' => $document_type])->asArray()->all();
}
else {
$template = Template::find()->asArray()->all();
if (empty($templateList)) {
throw new NotFoundHttpException('No templates found');
}
if (empty($template)) {
throw new NotFoundHttpException('Documents are not assigned');
return $templateList;
}
return $template;
}
public function actionGetTemplateFields(): array
/**
* @throws NotFoundHttpException
*/
public function actionGetTemplateFields($template_id): array
{
$template_id = Yii::$app->request->get('template_id');
if (empty($template_id) or !is_numeric($template_id)) {
throw new NotFoundHttpException('Incorrect template ID');
}
$templates = Template::find()
->joinWith('templateDocumentFields.field')
->where(['template.id' => $template_id])
->asArray()
->all();
$templateWithFields = TemplateService::getTemplateWithFields($template_id);
if (empty($templates)) {
throw new NotFoundHttpException('Documents are not assigned');
if (empty($templateWithFields)) {
throw new NotFoundHttpException('No template found');
}
return $templates;
return $templateWithFields;
}
/**
* @throws NotFoundHttpException
*/
public function actionGetTemplate($template_id): array
{
if (empty($template_id) or !is_numeric($template_id)) {
throw new NotFoundHttpException('Incorrect template ID');
}
$template = TemplateService::getTemplate($template_id);
if (empty($template)) {
throw new NotFoundHttpException('No template found');
}
return $template;
}
}

View File

@ -31,7 +31,7 @@ class UserQuestionnaireController extends ApiController
/**
* @throws NotFoundHttpException
*/
public function actionQuestionnairesList(): array
public function actionQuestionnairesList()//: array
{
$user_id = Yii::$app->request->get('user_id');
@ -40,20 +40,20 @@ class UserQuestionnaireController extends ApiController
throw new NotFoundHttpException('Incorrect user ID');
}
$userQuestionnaireModel = UserQuestionnaire::findActiveUserQuestionnaires($user_id);
if(empty($userQuestionnaireModel)) {
$userQuestionnaireModels = UserQuestionnaire::findActiveUserQuestionnaires($user_id);
if(empty($userQuestionnaireModels)) {
throw new NotFoundHttpException('Active questionnaire not found');
}
array_walk( $userQuestionnaireModel, function(&$arr){
array_walk( $userQuestionnaireModels, function(&$arr){
unset(
$arr['questionnaire_id'],
$arr['created_at'],
$arr['updated_at'],
// $arr['created_at'],
// $arr['updated_at'],
$arr['id'],
);
});
return $userQuestionnaireModel;
return $userQuestionnaireModels;
}
}

View File

@ -18,6 +18,7 @@ class ReportSearchForm extends Model
* @var false
*/
public $byDate;
public $date;
public function __construct($config = [])
{
@ -27,6 +28,7 @@ class ReportSearchForm extends Model
$this->toDate = date('Y-m-d', time());
$this->fromDate = date('Y-m-01', time());
$this->date = date('Y-m-d');
$this->byDate = false;
parent::__construct($config);
@ -36,7 +38,7 @@ class ReportSearchForm extends Model
{
return [
[['byDate'], 'safe'],
[['fromDate', 'toDate'], 'date', 'format' => 'php:Y-m-d'],
[['fromDate', 'toDate', 'date'], 'date', 'format' => 'php:Y-m-d'],
[['limit', 'offset', 'user_id'], 'integer', 'min' => 0],
];
}
@ -47,7 +49,7 @@ class ReportSearchForm extends Model
->with('task');
if ($this->byDate) {
$queryBuilder->andWhere(['reports.created_at' => $this->byDate]);
$queryBuilder->andWhere(['reports.created_at' => $this->date]);
} else {
$queryBuilder->andWhere(['between', 'reports.created_at', $this->fromDate, $this->toDate]);
}