diff --git a/common/services/InterviewRequestService.php b/common/services/InterviewRequestService.php new file mode 100644 index 0000000..2d99e48 --- /dev/null +++ b/common/services/InterviewRequestService.php @@ -0,0 +1,27 @@ +attributes = $attributes; + + $interviewRequest->created_at = time(); + $interviewRequest->user_id = \Yii::$app->user->id; + + if ($interviewRequest->save()) { + \Yii::$app->telegram_bot->sendRenderedMessage('interview_request', $attributes); + } + + return $interviewRequest; + } + +} \ No newline at end of file diff --git a/common/services/ProfileService.php b/common/services/ProfileService.php index fa54657..fc47886 100644 --- a/common/services/ProfileService.php +++ b/common/services/ProfileService.php @@ -4,59 +4,120 @@ namespace common\services; use common\models\Manager; use common\models\ManagerEmployee; +use common\models\UserCard; +use frontend\modules\api\models\ProfileSearchForm; +use Yii; +use yii\web\BadRequestHttpException; +use yii\web\ServerErrorHttpException; class ProfileService { - private $searcherID; - private $id; - - public function __construct($searcherID, $id) + /** + * @throws ServerErrorHttpException + */ + public static function getMainData($user_id): array { - $this->searcherID = $searcherID; - $this->id = $id; + $userCard = UserCard::findOne(['id_user' => $user_id]); + if (empty($userCard)) { + throw new ServerErrorHttpException(json_encode($userCard->errors)); + } + return array('fio' => $userCard->fio, + 'photo' => $userCard->photo, + 'gender' => $userCard->gender, + 'level' => $userCard->level, + 'years_of_exp' => $userCard->years_of_exp, + 'specification' => $userCard->specification, + 'position_name' => $userCard->position->name); } - public function checkReportePermission() + /** + * @throws BadRequestHttpException + */ + public static function getProfile($id, $request)//: ?array { - if ($this->isMyProfile() or $this->isMyEmployee()) { + $searchModel = new ProfileSearchForm(); + $searchModel->attributes = $request; + + if ($id) { + return $searchModel->byId(); + } + return $searchModel->byParams(); + } + + /** + * @throws BadRequestHttpException + */ + public static function getProfileWithReportPermission($user_card_id): ?array + { + if (UserCard::find()->where(['id' => $user_card_id])->exists()) { + + $searchModel = new ProfileSearchForm(); + $searchModel->id = $user_card_id; + $profile = $searchModel->byId(); + + self::addPermission($profile, $user_card_id); + return $profile; + } + throw new BadRequestHttpException(json_encode('There is no user with this id')); + } + + private static function addPermission(&$profile, $user_card_id) + { + $searcherCardID = self::getSearcherCardID(Yii::$app->user->getId()); + if (self::checkReportPermission($user_card_id, $searcherCardID)) { + $profile += ['report_permission' => '1']; + } else { + $profile += ['report_permission' => '0']; + } + } + + private static function getSearcherCardID($user_id): int + { + return UserCard::findOne(['id_user' => $user_id])->id; + } + + private static function checkReportPermission($user_card_id, $searcherCardID): bool + { + if (self::isMyProfile($user_card_id, $searcherCardID) + or self::isMyEmployee($user_card_id, $searcherCardID)) { return true; } return false; } - private function isMyProfile() + private static function isMyProfile($user_card_id, $searcherCardID): bool { - if ($this->id == $this->searcherID) { + if ($user_card_id == $searcherCardID) { return true; } return false; } - private function isMyEmployee() + private static function isMyEmployee($user_card_id, $searcherCardID): bool { - if (!$this->amIManager()) { - return false; - } + if (!self::amIManager($searcherCardID)) { + return false; + } - if ($this->isMyEmploee()) { - return true; - } - return false; - } - - private function amIManager() - { - if (Manager::find()->where(['user_card_id' => $this->searcherID])->exists()) { + if (self::isMyEmployer($user_card_id, $searcherCardID)) { return true; } return false; } - private function isMyEmploee() + private static function amIManager($searcherCardID): bool { - $manager = Manager::find()->where(['user_card_id' => $this->searcherID])->one(); + if (Manager::find()->where(['user_card_id' => $searcherCardID])->exists()) { + return true; + } + return false; + } + + private static function isMyEmployer($user_card_id, $searcherCardID): bool + { + $manager = Manager::find()->where(['user_card_id' => $searcherCardID])->one(); $exist = ManagerEmployee::find() - ->where(['manager_id' => $manager->id, 'user_card_id' => $this->id]) + ->where(['manager_id' => $manager->id, 'user_card_id' => $user_card_id]) ->exists(); if ($exist) { @@ -64,7 +125,4 @@ class ProfileService } return false; } - - - } \ No newline at end of file diff --git a/common/services/UserCardService.php b/common/services/UserCardService.php deleted file mode 100644 index bb743c2..0000000 --- a/common/services/UserCardService.php +++ /dev/null @@ -1,27 +0,0 @@ - $user_id]); - if (empty($userCard)) { - throw new ServerErrorHttpException(json_encode($userCard->errors)); - } - return array('fio' => $userCard->fio, - 'photo' => $userCard->photo, - 'gender' => $userCard->gender, - 'level' => $userCard->level, - 'years_of_exp' => $userCard->years_of_exp, - 'specification' => $userCard->specification, - 'position_name' => $userCard->position->name); - } -} \ No newline at end of file diff --git a/docs/api/interview.md b/docs/api/interview.md new file mode 100644 index 0000000..1cc58ac --- /dev/null +++ b/docs/api/interview.md @@ -0,0 +1,54 @@ +## Интервью +### Пригласить на собеседование +`https://guild.craft-group.xyz/api/interview-request/create-interview-request` + +

+ Для того, отправить приглашение профилю на собеседование, необходимо сделать + POST запрос на URL https://guild.craft-group.xyz/api/interview-request/create-interview-request +

+

+ Возможные параметры: +

+ + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ email* + + Почта пользователя, который хочет пригласить на собеседование. +
+ profile_id* + + Идентификатор профиля. +
+ phone + + Телефон. +
+ comment + + Дополнительные пожелания по собеседованию. +
+ diff --git a/docs/api/main.md b/docs/api/main.md index b431d96..5bd9dde 100755 --- a/docs/api/main.md +++ b/docs/api/main.md @@ -7,191 +7,6 @@ Чтобы получить популярные навыки нужно сделать GET запрос на URL https://guild.craft-group.xyz/api/skills/skills-on-main-page

-## Профиль -### Список -`https://guild.craft-group.xyz/api/profile` -

- Для получения списка профилей необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/profile -

-

- Возможные параметры: -

- - - - - - - - - - - - - - - - - -
- Параметры - - Значение -
- get-document-list - - Количество профилей, которое вернет сервер при запросе. -
- offset - - Количество записей на которое нужно отступить в списке профилей. -
- skills - - Идентификаторы навыков по которым нужно отфильтровать профили. -
-

- Пример запроса: -

- -`https://guild.craft-group.xyz/api/profile?limit=5&offset=5&skills=1,2` - -

- Возвращает массив объектов Профилей.
- Каждый объект Профиля имеет такой вид: -

- -```json5 -{ - "id": "1", - "fio": "f23f", - "passport": "f23", - "photo": "''", - "email": "f", - "gender": "1", - "dob": "2021-09-17", - "status": "2", - "created_at": "2021-09-08 16:30:34", - "updated_at": "2021-09-09 08:41:02", - "resume": "", - "salary": "", - "position_id": "1", - "deleted_at": null, - "id_user": "1", - "city": "", - "link_vk": "", - "link_telegram": "", - "vc_text": "", - "level": "2", // - "vc_text_short": "", - "years_of_exp": "0", - "specification": "", - "skillValues": [ //Массив навыков привязанных к этому профилю - { - "id": "1", - "card_id": "1", //card_id из таблицы card_skill - "skill_id": "1",//skill_id из таблицы card_skill - "skill": { - "id": "1", //id из таблицы skill - "name": "SQL", - "category_id": "1" - } - }, - //... - ], - "achievements": [ //Массив достижений привязанных к этому профилю - { - "id": "7", - "user_card_id": "1",//user_card_id из таблицы achievement_user_card - "achievement_id": "1",//achievement_id из таблицы achievement_user_card - "achievement": { - "id": "1", //id из таблицы achievement - "slug": "newguy", - "title": "Новичок", - "img": "", - "description": "Ты начал у нас работу", - "status": "1" // 1 - Активно, 2 - Неактивно - } - }, - //... - ] -} -``` - - -### Одна запись -`https://guild.craft-group.xyz/api/profile/{id}` - -

- Для того, чтобы получить данные одной записи необходимо отправить GET запрос - на URL https://guild.craft-group.xyz/api/profile/{id} , где id это идентификатор - профиля. -

-

- Пример запроса: -

- -`https://guild.craft-group.xyz/api/profile/6` - -

- Возвращает объект Профиля.
- Как выглядит можно посмотреть выше. -

- - -### Пригласить на собеседование -`https://guild.craft-group.xyz/api/profile/add-to-interview` - -

- Для того, отправить приглашение профилю на собеседование, необходимо сделать - POST запрос на URL https://guild.craft-group.xyz/api/profile/add-to-interview -

-

- Возможные параметры: -

- - - - - - - - - - - - - - - - - - - - - -
- Параметры - - Значение -
- email* - - Почта пользователя, который хочет пригласить на собеседование. -
- profile_id* - - Идентификатор профиля. -
- phone - - Телефон. -
- comment - - Дополнительные пожелания по собеседованию. -
- ## Отчет ### Список `https://guild.craft-group.xyz/api/reports` @@ -2406,7 +2221,7 @@ } ``` ### Назначить сотрудника на задачу -`https://guild.craft-group.xyz/api/task-user/get-task-users` +`https://guild.craft-group.xyz/api/task-user/set-task-users`

Для назначения исполнителя необходимо отправить POST запрос на URL https://guild.craft-group.xyz/api/task-user/set-task-user

diff --git a/docs/api/profile.md b/docs/api/profile.md new file mode 100644 index 0000000..f795fa9 --- /dev/null +++ b/docs/api/profile.md @@ -0,0 +1,308 @@ +# Профиль +## Методы + + + + + + + + + + + + + + + + + + + + + +
+ Метод + + Описание +
+ api/profile + + Возвращает список профилей +
+ api/profile/{id} + + Возвращает один профиль +
+ profile/profile-with-report-permission + + Получить профиль с флагом прав на просмотр отчётов этого пользователя +
+ profile/get-main-data + + Получить получить основные данные профиля +
+ +### Список +`https://guild.craft-group.xyz/api/profile` +

+ Для получения списка профилей необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/profile +

+

+ Возможные параметры: +

+ + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ get-document-list + + Количество профилей, которое вернет сервер при запросе. +
+ offset + + Количество записей на которое нужно отступить в списке профилей. +
+ skills + + Идентификаторы навыков по которым нужно отфильтровать профили. +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/profile?limit=5&offset=5&skills=1,2` + +

+ Возвращает массив объектов Профилей.
+ Каждый объект Профиля имеет такой вид: +

+ +```json5 +{ + "id": "1", + "fio": "f23f", + "passport": "f23", + "photo": "''", + "email": "f", + "gender": "1", + "dob": "2021-09-17", + "status": "2", + "created_at": "2021-09-08 16:30:34", + "updated_at": "2021-09-09 08:41:02", + "resume": "", + "salary": "", + "position_id": "1", + "deleted_at": null, + "id_user": "1", + "city": "", + "link_vk": "", + "link_telegram": "", + "vc_text": "", + "level": "2", // + "vc_text_short": "", + "years_of_exp": "0", + "specification": "", + "skillValues": [ //Массив навыков привязанных к этому профилю + { + "id": "1", + "card_id": "1", //card_id из таблицы card_skill + "skill_id": "1",//skill_id из таблицы card_skill + "skill": { + "id": "1", //id из таблицы skill + "name": "SQL", + "category_id": "1" + } + }, + //... + ], + "achievements": [ //Массив достижений привязанных к этому профилю + { + "id": "7", + "user_card_id": "1",//user_card_id из таблицы achievement_user_card + "achievement_id": "1",//achievement_id из таблицы achievement_user_card + "achievement": { + "id": "1", //id из таблицы achievement + "slug": "newguy", + "title": "Новичок", + "img": "", + "description": "Ты начал у нас работу", + "status": "1" // 1 - Активно, 2 - Неактивно + } + }, + //... + ] +} +``` + + +### Одна запись +`https://guild.craft-group.xyz/api/profile/{id}` + +

+ Для того, чтобы получить данные одной записи необходимо отправить GET запрос + на URL https://guild.craft-group.xyz/api/profile/{id} , где id это идентификатор + профиля. +

+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/profile/6` + +

+ Возвращает объект Профиля.
+ Как выглядит можно посмотреть выше. +

+ +### Получить профиль с флагом прав на просмотр отчётов этого пользователя +`https://guild.craft-group.xyz/api/profile/profile-with-report-permission` + +

+ Для получения профиля пользователя с флагом прав на просмотр отчётов этого пользователя, необходимо сделать + GET запрос на URL https://guild.craft-group.xyz/api/profile/add-to-interview +

+

+ Возможные параметры: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ id + + ID профиля пользователя +
+ +## Основные данные пользователя + +`https://guild.craft-group.xyz/api/profile/get-main-data?user_id=1` +

+ Требуемые параметры: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + Id профиля пользователя +
+ +

+ Возвращает объект Пользователь.
+ Каждый объект Пользователь имеет такой вид: +

+ +```json5 +{ + "fio": "Тест менеджер для апи запроса", + "photo": null, + "gender": 1, + "level": 2, + "years_of_exp": null, + "specification": null, + "position_name": "Должность 1" +} +``` + +

+ Возвращаемые параметры: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ fio + + ФИО +
+ photo + + Ссылка на фото +
+ gender + + Пол +
+ level + + Уровень +
+ years_of_exp + + Лет опыта +
+ position_name + + Должность +
+ diff --git a/docs/api/questionnaire.md b/docs/api/questionnaire.md new file mode 100644 index 0000000..5bcb6b1 --- /dev/null +++ b/docs/api/questionnaire.md @@ -0,0 +1,975 @@ +## Анкеты + +## Методы + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Метод + + Описание +
+ questionnaire/questionnaires-list + + Возвращает список анкет +
+ questionnaire/questionnaire-completed + + Завершение прохождение анкеты, проверка ответов +
+ questionnaire/get-points-number + + Число балов в анкете +
+ questionnaire/get-question-number + + Число вопросов в анкете +
+ question/get-questions + + Вопросы анкеты +
+ answer/get-answers + + Список возможных ответов на вопрос +
+ user-response/set-response + + Сохранить ответ пользователя +
+ user-response/set-responses + + Сохранить массив ответов пользователя +
+ get + + Возвращает менеджера +
+ +### Список анкет + +`https://guild.craft-group.xyz/api/user-questionnaire/questionnaires-list` +

+ Для получения списка анкет необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/user-questionnaire/questionnaires-list +

+ +

+ Требуемые параметры запроса: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя(int) +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/user-questionnaire/questionnaires-list?user_id=1` + +

+ Возвращает массив объектов записи Назначенная анкета.
+ Каждый объектимеет такой вид: +

+ +```json5 + { + "user_id": 1, + "uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", + "score": 11, + "status": 2, + "percent_correct_answers": 0.25, + "testing_date": "2022-03-17 11:14:22", + "questionnaire_title": "Кат1 Анкета 1 активна" +} +``` + +

+ Возвращаемые параметры объекта анкета: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя(int) +
+ uuid + + uuid анкеты пользователя +
+ score + + Полученные балы(int) +
+ status + + Статус: 0 - не активен; 1 - активен; 2 - завершён; 3 - на проверке; +
+ percent_correct_answers + + Процент правильных ответов(float) +
+ testing_date + + Дата тестирования +
+ questionnaire_title + + Название анкеты +
+ +

+ Передаваемые параметры объекта вопроса: +

+ + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя(int) +
+ score + + Полученные балы(int) +
+ percent_correct_answers + + Процент правильных ответов(float) +
+

+ Если пользователь не найден или у пользователя нет активных анкет будет отправлено следующее сообщение: +

+ +```json5 +{ + "name": "Not Found", + "message": "Active questionnaire not found", + "code": 0, + "status": 404, + "type": "yii\\web\\NotFoundHttpException" +} +``` + +### Проверить ответы в анкете + +`https://guild.craft-group.xyz/api/user-questionnaire/questionnaire-completed` +

+ Для выполнения проверки анкеты необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/user-questionnaire/questionnaire-completed +

+ +

+ Требуемые параметры запроса: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ user_questionnaire_uuid + + UUID анкеты назначеной пользователю +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/user-questionnaire/questionnaire-completed?user_questionnaire_uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` + +

+ Возвращает массив объектов Вопросов.
+ Каждый объект Вопрос имеет такой вид: +

+ +```json5 +{ + "id": 1, + "questionnaire_id": 1, + "user_id": 1, + "uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", + "created_at": "2021-10-20 13:06:12", + "updated_at": { + "expression": "NOW()", + "params": [] + }, + "score": 4, + "status": 1, + "percent_correct_answers": 0.5, + "testing_date": null +} +``` + +### Число балов в анкете + +`https://guild.craft-group.xyz/api/user-questionnaire/get-points-number?user_questionnaire_uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` +

+ Для максимального числа балов в анкеты необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/user-questionnaire/get-points-number +

+ +

+ Требуемые параметры запроса: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ user_questionnaire_uuid + + UUID анкеты назначеной пользователю +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/user-questionnaire/get-points-number?user_questionnaire_uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` + +

+ Возвращает максимально возможное число балов за анкету b>.
+ Объект Ответа имеет такой вид: +

+ +```json5 +{ + "sum_point": "61" +} +``` + +### Число вопросов в анкете + +`https://guild.craft-group.xyz/api/user-questionnaire/get-question-number?user_questionnaire_uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` +

+ Для числа вопросов в анкете необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/user-questionnaire/get-question-number +

+ +

+ Требуемые параметры запроса: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ user_questionnaire_uuid + + UUID анкеты назначеной пользователю +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/user-questionnaire/get-question-number?user_questionnaire_uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` + +

+ Возвращает число вопросов в анкете b>.
+ Объект Ответа имеет такой вид: +

+ +```json5 +{ + "question_number": "7" +} +``` + +### Вопросы анкеты + +`https://guild.craft-group.xyz/api/question/get-questions` +

+ Для получения вопросов анкеты необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/question/get-questions +

+ +

+ Требуемые параметры запроса: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ uuid + + UUID анкеты назначеной пользователю +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/question/get-questions?uuid=d222f858-60fd-47fb-8731-dc9d5fc384c5` + +

+ Возвращает массив объектов Вопросов.
+ Каждый объект Вопрос имеет такой вид: +

+ +```json5 +{ + "id": "4", + "question_type_id": "2", + "question_body": "Один ответ1", + "question_priority": null, + "next_question": null, + "time_limit": "00:22:00" +} +``` + +

+ Передаваемые параметры объекта вопроса: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ id + + ID вопроса(int) +
+ question_type_id + + ID типа вопроса(int) +
+ question_body + + Вопрос(string) +
+ question_priority + + Приоритет вопроса(int)(не используется) +
+ next_question + + Следующий вопрос(int)(не используется) +
+ time_limit + + Ограничение времени на ответ(time) +
+

+ Если вопрос не найден или не предпологает передачу ответов будет отправлено следующее сообщение: +

+ +```json5 +{ + "name": "Not Found", + "message": "Questions not found", + "code": 0, + "status": 404, + "type": "yii\\web\\NotFoundHttpException" +} +``` + +### Ответы на вопрос + +`https://guild.craft-group.xyz/api/answer/get-answers` +

+ Для получения вариантов ответов на вопрос анкеты нужно сделать GET запрос на URL https://guild.craft-group.xyz/api/answer/get-answers +

+ +

+ Требуемые параметры: +

+ + + + + + + + + + +
+ Параметры + + Значение +
+ question_id + + ID вопроса +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/answer/get-answers?question_id=7` + +

+ Возвращает массив объектов Ответов.
+ Каждый объект Ответа имеет такой вид: +

+ +```json5 +[ + { + "id": "12", + "question_id": "7", + "answer_body": "Неск вар1 отв1 истина" + }, +] + +``` + +

+ Передаваемые параметры объекта вопроса: +

+ + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ id + + ID вопроса(int) +
+ question_id + + ID вопроса(int) +
+ answer_body + + Ответ(string) +
+

+ Если ответы не найдены или вопрос не предпологает их наличие(открытый вопрос) будет отправлено следующее сообщение: +

+ +```json5 +{ + "name": "Not Found", + "message": "Answer not found or question inactive", + "code": 0, + "status": 404, + "type": "yii\\web\\NotFoundHttpException" +} +``` + +### Один ответ пользователя + +`https://guild.craft-group.xyz/api/user-response/set-response` +

+ Для добавления ответа на вопрос от пользователя необходимо сделать POST запрос на URL https://guild.craft-group.xyz/api/user-response/set-response +

+ +

+ Тело запроса содержит: +

+ + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя +
+ question_id + + ID вопроса(int) +
+ response_body + + Ответ пользователя(string 255) +
+ user_questionnaire_uuid + + UUID анкеты назначенной пользователю(string 36) +
+

+ Пример тела запроса: +

+ +```json5 +{ + "user_id": "1", + "question_id": "7", + "response_body": "oooooooooooo111111111", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5" +} +``` + +`https://guild.craft-group.xyz/api/user-response/set-response` + +

+ Возвращает объект Ответа.
+ Объект Ответа имеет такой вид: +

+ +```json5 +{ + "user_id": "1", + "question_id": "7", + "response_body": "oooooooooooo111111111", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", + "created_at": { + "expression": "NOW()", + "params": [] + }, + "updated_at": { + "expression": "NOW()", + "params": [] + }, + "id": 191, + "answer_flag": 0 +} +``` + +

+ Ответ содержит: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя +
+ question_id + + ID вопроса(int) +
+ response_body + + Ответ пользователя(string 255) +
+ user_questionnaire_uuid + + UUID анкеты назначенной пользователю(string 36) +
+ answer_flag + + Флаг ответа(1 - верно, 0 - ложно). Если отправлен ответ на открытый вопрос, флаг ответа не будет возвращаться до момента проверки в админ панели. +
+ +

+ В случаии ошибки в запросе будет отправлено сообщение следующего вида: +

+ +```json5 +{ + "name": "Bad Request", + "message": "{\"question_id\":[\"\В\о\п\р\о\с is invalid.\"]}", + "code": 0, + "status": 400, + "type": "yii\\web\\BadRequestHttpException" +} +``` + +### Массив ответов пользователя + +`https://guild.craft-group.xyz/api/user-response/set-responses` +

+ Для добавления массива ответов на вопросы от пользователя необходимо сделать POST запрос на URL https://guild.craft-group.xyz/api/user-response/set-responses +

+ +

+ Тело запроса содержит JSON c массивом ответов со следующими параметрами: +

+ + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя +
+ question_id + + ID вопроса(int) +
+ response_body + + Ответ пользователя(string 255) +
+ user_questionnaire_uuid + + UUID анкеты назначенной пользователю(string 36) +
+

+ Пример тела запроса: +

+ +```json5 +{ + "userResponses": [ + { + "user_id": "1", + "question_id": "7", + "response_body": "oooooooooooo111111111", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5" + }, + { + "user_id": "1", + "question_id": "4", + "response_body": "oooooooooooo2222222", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5" + } + ] +} +``` + +

+ Возвращает массив объектов ОтветПользователя.
+ Пример: +

+ +```json5 +[ + { + "user_id": "1", + "question_id": "7", + "response_body": "oooooooooooo111111111", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", + "created_at": { + "expression": "NOW()", + "params": [] + }, + "updated_at": { + "expression": "NOW()", + "params": [] + }, + "id": 192, + "answer_flag": 0 + }, + { + "user_id": "1", + "question_id": "7", + "response_body": "oooooooooooo111111111", + "user_questionnaire_uuid": "d222f858-60fd-47fb-8731-dc9d5fc384c5", + "created_at": { + "expression": "NOW()", + "params": [] + }, + "updated_at": { + "expression": "NOW()", + "params": [] + }, + "id": 193, + "answer_flag": 0 + } +] +``` + +

+ Ответ содержит: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_id + + ID пользователя +
+ question_id + + ID вопроса(int) +
+ response_body + + Ответ пользователя(string 255) +
+ user_questionnaire_uuid + + UUID анкеты назначенной пользователю(string 36) +
+ answer_flag + + Флаг ответа(1 - верно, 0 - ложно) +
+

+ В случаии ошибки в запросе будет отправлено сообщение следующего вида: +

+ +```json5 +{ + "name": "Bad Request", + "message": "{\"question_id\":[\"\В\о\п\р\о\с is invalid.\"]}", + "code": 0, + "status": 400, + "type": "yii\\web\\BadRequestHttpException" +} +``` diff --git a/docs/api/reports.md b/docs/api/reports.md new file mode 100644 index 0000000..97fe3dc --- /dev/null +++ b/docs/api/reports.md @@ -0,0 +1,434 @@ +## Отчеты +## Методы + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Метод + + Описание +
+ api/reports + + Список отчётов +
+ api/reports/{id} + + Один отчёт +
+ find-by-date + + Отчёт по дате +
+ create + + Создать отчёт +
+ delete + + Удалить отчёт +
+ update + + Изменить отчёт +
+ +### Список +`https://guild.craft-group.xyz/api/reports` +

+ Для получения списка отчетов необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/reports +

+ +

+ Возможные параметры: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ fromDate* + + Дата (yyyy-mm-dd) начала поиска отчетов. +
+ toDate + + Дата (yyyy-mm-dd) окончания поиска отчетов. +
+ limit + + Количество отчетов, которое вернет сервер при запросе (по умолчанию 10). +
+ offset + + Количество записей на которое нужно отступить в списке отчетов. +
+ user_id + + Идентификатор карточки пользователя отчета. +
+

+ Пример запроса: +

+ +`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}` +

+ Для получения отчета необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/reports/{id} +

+ +

+ Параметры: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ id* + + ID отчета. +
+

+ Пример запроса на просмотр отчета с ID 13: +

+ +`https://guild.craft-group.xyz/api/reports/13` + +### Отчёт по дате +`https://guild.craft-group.xyz/api/reports/find-by-date` +

+ Для получения отчета необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/reports/find-by-date +

+ +

+ Требуемые параметры: +

+ + + + + + + + + + + + + +
+ Параметры + + Значение +
+ user_card_id* + + ID профиля пользователя +
+ date* + + Дата в формате: Y-m-d +
+

+ Пример запроса : +

+ +`https://guild.craft-group.xyz/api/reports/find-by-date?user_card_id=17&date=2022-02-14` + +

+ Пример ответа: +

+ +```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` + +

+ Для того, отправить приглашение профилю на собеседование, необходимо сделать + POST запрос на URL https://guild.craft-group.xyz/api/reports/create +

+

+ Возможные параметры: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ created_at* + + Дата (yyyy-mm-dd) создания. +
+ user_card_id* + + Идентификатор карточки пользователя. +
+ tasks* + + JSON массив содержащий объекты задач +
+[{ 
+    "task" : "Рефакторинг",
+    "created_at": 1638260728,
+    "status": 1,
+    "minutes_spent": 26,
+    "hours_spent" : 3
+}]
+
+
+ difficulties + + Сложности. +
+ tomorrow + + Планы на завтра. +
+ status + + Номер статуса. +
+ +### Удалить отчет +`https://guild.craft-group.xyz/api/reports/delete` + +

+ Для удаления отчета необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/reports/delete +

+ +

+ Возможные параметры: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ id* + + Идентификатор отчета. +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/reports/delete?id=17` +### Обновить отчет + +`https://guild.craft-group.xyz/api/reports/update` + +

+ Для удаления отчета необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/reports/update +

+ +

+ Возможные параметры: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ id* + + Идентификатор отчета. +
+ created_at + + Дата (yyyy-mm-dd) создания. +
+ today + + Сделанное сегодня. +
+ difficulties + + Сложности. +
+ tomorrow + + Планы на завтра. +
+ status + + Номер статуса. +
+

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/reports/update?id=18&created_at=2021-09-17&today=0&difficulties=diff&tomorrow=new task&status=1` diff --git a/docs/api/skills.md b/docs/api/skills.md new file mode 100644 index 0000000..6e21422 --- /dev/null +++ b/docs/api/skills.md @@ -0,0 +1,6 @@ +## Навыки +### Популярные навыки +`https://guild.craft-group.xyz/api/skills/skills-on-main-page` +

+ Чтобы получить популярные навыки нужно сделать GET запрос на URL https://guild.craft-group.xyz/api/skills/skills-on-main-page +

diff --git a/docs/api/task-user.md b/docs/api/task-user.md new file mode 100644 index 0000000..a21e905 --- /dev/null +++ b/docs/api/task-user.md @@ -0,0 +1,200 @@ +## Исполнители задачи +## Методы + + + + + + + + + + + + + +
+ Метод + + Описание +
+ get-task-users + + Список исплнителей задачи +
+ set-task-users + + Назначить исполнителя на задачу +
+ +### Список исполнителей задачи +`https://guild.craft-group.xyz/api/task-user/get-task-users` +

+ Для получения списка исполнителей необходимо отправить GET запрос на URL https://guild.craft-group.xyz/api/task-user/get-task-users +

+ +

+ Требуемые параметры: +

+ + + + + + + + + +
+ Параметры + + Значение +
+ task_id + + ID задачи +
+ +

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/task-user/get-task-users?task_id=10` + +

+ Возвращает массив сотрудников проекта закреплённых за задачей.
+ Каждый ответ имеет такой вид: +

+ +```json5 +[ + { + "id": 5, + "task_id": 10, + "project_user_id": 1 + }, + { + "id": 7, + "task_id": 10, + "project_user_id": 5 + } +] +``` +

+ Параметры объекта Исполнитель: +

+ + + + + + + + + + + + + + + + + +
+ Параметры + + Значение +
+ id + + ID исполнителя задачи(int) +
+ task_id + + ID задачи(int) +
+ project_user_id + + ID сотрудника на проекте(int) +
+

+ Если задача не найдена будет отправлено следующее сообщение: +

+ +```json5 +{ + "name": "Not Found", + "message": "The task does not exist or there are no employees for it", + "code": 0, + "status": 404, + "type": "yii\\web\\NotFoundHttpException" +} +``` +### Назначить сотрудника на задачу +`https://guild.craft-group.xyz/api/task-user/set-task-users` +

+ Для назначения исполнителя необходимо отправить POST запрос на URL https://guild.craft-group.xyz/api/task-user/set-task-user +

+ +

+ Требуемые параметры: +

+ + + + + + + + + + + + + +
+ Параметры + + Значение +
+ task_id + + ID задачи +
+ project_user_id + + ID сотрудника на проекте +
+ +

+ Пример запроса: +

+ +`https://guild.craft-group.xyz/api/task-user/set-task-user` + +

+ Возвращает объект Исполнителя задачи.
+ Каждый ответ имеет такой вид: +

+ +```json5 +{ + "task_id": "10", + "project_user_id": "5", + "id": 8 +} +``` + +

+ Если задача не найдена будет отправлено следующее сообщение: +

+ +```json5 +{ + "name": "Bad Request", + "message": "{\"task_id\":[\"\З\а\д\а\ч\а is invalid.\"]}", + "code": 0, + "status": 400, + "type": "yii\\web\\BadRequestHttpException" +} +``` \ No newline at end of file diff --git a/docs/api/task.md b/docs/api/task.md index a3f39b7..2e84803 100644 --- a/docs/api/task.md +++ b/docs/api/task.md @@ -236,7 +236,7 @@ } ``` -## Обновить документ +## Обновить задачу `https://guild.craft-group.xyz/api/task/update`

diff --git a/frontend/modules/api/controllers/InterviewRequestController.php b/frontend/modules/api/controllers/InterviewRequestController.php new file mode 100644 index 0000000..8ffd2f6 --- /dev/null +++ b/frontend/modules/api/controllers/InterviewRequestController.php @@ -0,0 +1,33 @@ + ['post'] + ]; + } + + /** + * @throws InvalidConfigException + * @throws ServerErrorHttpException + */ + public function actionCreateInterviewRequest(): InterviewRequest + { + $InterviewRequestModel = InterviewRequestService::createInterviewRequest(Yii::$app->getRequest()->getBodyParams()); + if ($InterviewRequestModel->errors) { + throw new ServerErrorHttpException(json_encode($InterviewRequestModel->errors)); + } + return $InterviewRequestModel; + } +} \ No newline at end of file diff --git a/frontend/modules/api/controllers/ManagerController.php b/frontend/modules/api/controllers/ManagerController.php index 6d75aff..b31a385 100644 --- a/frontend/modules/api/controllers/ManagerController.php +++ b/frontend/modules/api/controllers/ManagerController.php @@ -2,7 +2,6 @@ namespace frontend\modules\api\controllers; - use common\services\ManagerService; use yii\web\NotFoundHttpException; @@ -24,7 +23,7 @@ class ManagerController extends ApiController { $managers = ManagerService::getManagerList(); - if(empty($managers)) { + if (empty($managers)) { throw new NotFoundHttpException('Managers are not assigned'); } @@ -36,14 +35,13 @@ class ManagerController extends ApiController */ public function actionGetManagerEmployeesList($manager_id): array { - if(empty($manager_id) or !is_numeric($manager_id)) - { + if (empty($manager_id) or !is_numeric($manager_id)) { throw new NotFoundHttpException('Incorrect manager ID'); } $managerEmployeesList = ManagerService::getManagerEmployeesList($manager_id); - if(empty($managerEmployeesList)) { + if (empty($managerEmployeesList)) { throw new NotFoundHttpException('Managers are not assigned or employees are not assigned to him'); } @@ -55,14 +53,13 @@ class ManagerController extends ApiController */ public function actionGetManager($manager_id): array { - if(empty($manager_id) or !is_numeric($manager_id)) - { + if (empty($manager_id) or !is_numeric($manager_id)) { throw new NotFoundHttpException('Incorrect manager ID'); } $manager = ManagerService::getManager($manager_id); - if(empty($manager)) { + if (empty($manager)) { throw new NotFoundHttpException('There is no such manager'); } diff --git a/frontend/modules/api/controllers/ProfileController.php b/frontend/modules/api/controllers/ProfileController.php index 027b435..70c3a7c 100755 --- a/frontend/modules/api/controllers/ProfileController.php +++ b/frontend/modules/api/controllers/ProfileController.php @@ -2,117 +2,38 @@ namespace frontend\modules\api\controllers; -use common\behaviors\GsCors; -use common\classes\Debug; -use common\models\InterviewRequest; -use common\models\User; -use common\models\UserCard; use common\services\ProfileService; -use frontend\modules\api\models\ProfileSearchForm; -use kavalar\BotNotificationTemplateProcessor; -use kavalar\TelegramBotService; -use Yii; -use yii\filters\auth\CompositeAuth; -use yii\filters\auth\HttpBearerAuth; -use yii\filters\auth\QueryParamAuth; -use yii\filters\ContentNegotiator; -use yii\helpers\ArrayHelper; use yii\web\BadRequestHttpException; -use yii\web\Response; - +use yii\web\ServerErrorHttpException; class ProfileController extends ApiController { - - public function behaviors() + public function verbs(): array { - $parent = parent::behaviors(); - $b = [ - [ - 'class' => ContentNegotiator::className(), - 'formats' => [ - 'application/json' => Response::FORMAT_JSON, - ], - ], - 'authenticator' => [ - 'class' => CompositeAuth::class, - 'authMethods' => [ - HttpBearerAuth::class, - ], - ] + return [ + '' => ['get'], + 'profile-with-report-permission' => ['post', 'patch'] ]; - - return array_merge($parent, $b); } - public function actionIndex($id = null) + public function actionIndex($id = null): ?array { - $searchModel = new ProfileSearchForm(); - $searchModel->attributes = \Yii::$app->request->get(); - - if ($id) { - return $searchModel->byId(); - } - - return $searchModel->byParams(); + return ProfileService::getProfile($id, \Yii::$app->request->get()); } - public function actionProfileWithReportPermission($id) + /** + * @throws BadRequestHttpException + */ + public function actionProfileWithReportPermission($id): ?array { - $searchModel = new ProfileSearchForm(); - $searchModel->attributes = \Yii::$app->request->get(); - - $searcherUser = Yii::$app->user->getId(); - $searcherProfileId = UserCard::findOne($searcherUser)->id; - - if ($id && $searcherProfileId) { - if(!UserCard::find()->where(['id' => $id])->exists()) - { - throw new BadRequestHttpException(json_encode('There is no user with this id')); - } - $profile = $searchModel->byId(); - - $profileService = new ProfileService($searcherProfileId, $id); - - if($profileService->checkReportePermission()) { - $profile += ['report_permission' => '1']; - } - else { - $profile += ['report_permission' => '0']; - } - return $profile; - } - - throw new BadRequestHttpException(json_encode('Missing required parameter')); + return ProfileService::getProfileWithReportPermission($id); } - public function actionAddToInterview() + /** + * @throws ServerErrorHttpException + */ + public function actionGetMainData($user_id): array { - if (\Yii::$app->request->isPost) { - $attributes = \Yii::$app->request->post(); - - $model = new InterviewRequest(); - $model->attributes = $attributes; - $model->created_at = time(); - $model->user_id = \Yii::$app->user->id; - if ($model->save()) { - \Yii::$app->telegram_bot->sendRenderedMessage('interview_request', $attributes); - return ['status' => 'success']; - } - - \Yii::$app->response->statusCode = 400; - return ['status' => 'error', 'errors' => $model->errors]; - } + return ProfileService::getMainData($user_id); } - - public function actionMe() - { - if(isset(\Yii::$app->user->id)){ - $user = User::find()->with('userCard')->where(['id' => \Yii::$app->user->id])->one(); - } - - \Yii::$app->response->statusCode = 401; - return ['status' => 'error', 'errors' => 'No authorized']; - } - -} +} \ No newline at end of file diff --git a/frontend/modules/api/controllers/TaskController.php b/frontend/modules/api/controllers/TaskController.php index 62749ce..dd9a3ef 100644 --- a/frontend/modules/api/controllers/TaskController.php +++ b/frontend/modules/api/controllers/TaskController.php @@ -31,7 +31,6 @@ class TaskController extends ApiController if ($taskModel->errors) { throw new ServerErrorHttpException(json_encode($taskModel->errors)); } - return $taskModel; } @@ -39,23 +38,19 @@ class TaskController extends ApiController /** * @throws NotFoundHttpException */ - public function actionGetTaskList($project_id = null): array + public function actionGetTaskList($project_id = null): array { $tasks = array(); - if ($project_id) - { - if(empty($project_id) or !is_numeric($project_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 - { + } 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'); } return $tasks; @@ -66,13 +61,12 @@ class TaskController extends ApiController */ public function actionGetTask($task_id): Task { - if(empty($task_id) or !is_numeric($task_id)) - { + if (empty($task_id) or !is_numeric($task_id)) { throw new NotFoundHttpException('Incorrect task ID'); } $task = TaskService::getTask($task_id); - if(empty($task)) { + if (empty($task)) { throw new NotFoundHttpException('The task does not exist'); } @@ -87,8 +81,7 @@ class TaskController extends ApiController public function actionUpdate(): ?Task { $params = Yii::$app->request->getBodyParams(); - if (empty ($params['task_id']) or !TaskService::taskExists($params['task_id'])) - { + if (empty ($params['task_id']) or !TaskService::taskExists($params['task_id'])) { throw new NotFoundHttpException('The task does not exist'); } diff --git a/frontend/modules/api/controllers/TaskUserController.php b/frontend/modules/api/controllers/TaskUserController.php index 4cdb3eb..60951a8 100644 --- a/frontend/modules/api/controllers/TaskUserController.php +++ b/frontend/modules/api/controllers/TaskUserController.php @@ -9,19 +9,8 @@ use yii\rest\Controller; use yii\web\BadRequestHttpException; use yii\web\NotFoundHttpException; -class TaskUserController extends Controller +class TaskUserController extends ApiController { - public function behaviors(): array - { - $behaviors = parent::behaviors(); - - $behaviors['authenticator']['authMethods'] = [ - HttpBearerAuth::className(), - ]; - - return $behaviors; - } - public function verbs(): array { return [ diff --git a/frontend/modules/api/controllers/UserCardController.php b/frontend/modules/api/controllers/UserCardController.php deleted file mode 100644 index bdbebdd..0000000 --- a/frontend/modules/api/controllers/UserCardController.php +++ /dev/null @@ -1,24 +0,0 @@ - ['get'], - ]; - } - - /** - * @throws ServerErrorHttpException - */ - public function actionGetUserCard($user_id): array - { - return UserCardService::getUserCard($user_id); - } -} \ No newline at end of file