Skip to content
This repository was archived by the owner on Jul 3, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
__pycache__/
.vscode/
venv/
db.sqlite3
setup.cfg
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

108 changes: 46 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,48 @@
# Вакансия :: Программист Python

Разработка бизнес-системы с использованием веб-технологий. Автоматизация сервисов с большим количеством пользователей

## От вас

### Обязательно

- Знание синтаксиса языка Python
- Опыт разработки на Python не менее 1 года
- Базовые знания принципов работы Web
- Желание работать в команде и развиваться

### Приветствуется

- Навыки работы с Flask, Sanic, FastAPI
- Опыт работы с БД: PostgreSQL, MS SQL, MongoDB, ClickHouse
- Опыт разработки под ОС семейства GNU Linux, знание основных команд
- Работа с системами управления исходным кодом Git
- Знания базовых принципов разработки (тестирование, рефакторинг, Code Review, CI/CD)

### Будет круто, но не обязательно

- Знание английского языка на уровне чтения технической документации
- Участие в разработке Open Source проектов
- Наличие профиля на GitHub, Stack Overflow
- Наличие проектов которые можете показать нам
- Разработка с использованием TypeScript, знание современных frontend-библиотек и подходов к разработке

## У нас

- Полный рабочий день, гибкий обед и начало рабочего дня
- Полностью «белая» заработная плата с возможностью увеличения в процессе работы (зависит от отдачи сотрудника)
- Полис ДМС
- Дружелюбная команда с юмором, готовая поддержать и помочь
- Интересный проект и необычные задачи. Рутина тоже есть, но мы нацелены именно на продуктив
- Возможность одновременно участвовать в разных проектах и развивать другие компетенции (TS и все модное)
- Попробовать современные тренды и практики в разработке ПО
- Никаких опенспейсов и кубиклов, а комфортное пространство в центре Тюмени
- Готовы делиться опытом и знаниями, если вы готовы их получать

 

Если вакансия вас заинтересовала, но есть недопонимания и вопросы, свяжитесь с нами - обсудим, договоримся.
Большим плюсом будет выполнение тестового задания.
Если у вас есть опыт работы с 1С, то эта вакансия не для вас.

## Тестовое задание

Решение принимается в виде PR к текущему проекту.

<div id="header" align="center">
<h1>StatusHistory</h1>
<img src="https://img.shields.io/badge/Python-3.7.9-F8F8FF?style=for-the-badge&logo=python&logoColor=20B2AA">
<img src="https://img.shields.io/badge/Django-3.2.23-F8F8FF?style=for-the-badge&logo=django&logoColor=00FF00">
<img src="https://img.shields.io/badge/DjangoRestFramework-3.14.0-F8F8FF?style=for-the-badge&logo=django&logoColor=00FF00">
<img src="https://img.shields.io/badge/Docker-555555?style=for-the-badge&logo=docker&logoColor=2496ED">
</div>

# Документация API
Status History - **[API redoc](https://kaschenkkko.github.io/StatusHistory/)**

# Описание проекта:
Есть несколько рабочих сервисов, у каждого сервиса есть состояние работает/не работает/работает нестабильно.

Требуется написать API который:

1. Получает и сохраняет данные: имя, состояние, описание
2. Выводит список сервисов с актуальным состоянием
3. По имени сервиса выдает историю изменения состояния и все данные по каждому состоянию

Дополнительным плюсом будет

1. По указанному интервалу выдается информация о том сколько не работал сервис и считать SLA в процентах до 3-й запятой

Вывод всех данных должен быть в формате JSON
Написан API который:

1. Получает и сохраняет данные сервиса: имя, состояние, описание.
2. Выводит список сервисов с актуальным состоянием.
3. По id сервиса выдает историю изменения состояния и все данные по каждому состоянию.
4. По указанному интервалу выдаёт информация о том сколько не работал сервис и считает SLA в процентах до 3-й запятой.

# Описание API:
- **GET /api/services/** - выводит список сервисов с актуальным состоянием.
- **POST /api/services/** - добавление нового сервиса.
- **GET /api/history/{service_id}/** - выдает историю изменений состояния.
- **GET /api/{service_id}/{start_date}/{end_date}/**: выдаёт информация о том сколько не работал сервис и считает SLA.

# Запуск проекта:
- Клонируйте репозиторий и перейдите в него.
- Перейдите в папку **infra** и проверьте, что файл .env заполнен данными представленными ниже:
```
DEBUG=True
ALLOWED_HOSTS=127.0.0.1
```
- Из папки **infra** запустите docker-compose
```
~$ docker-compose up -d --build
```
- В контейнере web выполните миграции, создайте суперпользователя и соберите статику.
```
~$ docker-compose exec web python manage.py migrate
~$ docker-compose exec web python manage.py createsuperuser
~$ docker-compose exec web python manage.py collectstatic --no-input
```

После этого API проекта будет доступно по url-адресу [127.0.0.1/api/](http://127.0.0.1/api/)

Документация к API будет доступна по url-адресу [127.0.0.1/api/docs](http://127.0.0.1/api/docs/)
19 changes: 19 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Documentation API</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-url='./openapi-schema.yml'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"></script>
</body>
</html>
195 changes: 195 additions & 0 deletions docs/openapi-schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
openapi: 3.0.2
info:
title: 'StatusHistory'
version: ''
paths:
/api/services/:
get:
description: 'Список сервисов.'
parameters: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Services'
description: ''
tags:
- Сервисы
post:
description: 'Создание сервиса.'
parameters:
- name: name
required: true
in: query
description: 'Название сервиса'
example: 'Крутой сервис'
schema:
type: string
- name: description
required: true
in: query
description: 'Описание сервиса'
example: 'Описание крутого сервиса'
schema:
type: string
- name: status
required: false
in: query
description: 'Статус работы сервиса'
example: 'работает'
schema:
default: 'работает'
type: string
enum: ['работает', 'не работает', 'нестабильно']
responses:
'201':
content:
application/json:
schema:
$ref: "#/components/schemas/Service"
description: ''
tags:
- Сервисы
/api/history/{service_id}/:
get:
description: 'История изменений состояния работы сервиса.'
parameters:
- name: service_id
required: true
in: path
description: 'ID сервиса'
example: 3
schema:
type: integer
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/History'
description: ''
tags:
- История работы сервиса
/api/{service_id}/{start_date}/{end_date}/:
get:
operationId: Расчёт SLA
description: 'Информация о том сколько не работал сервис и расчёт SLA.'
parameters:
- name: service_id
required: true
in: path
description: 'ID сервиса'
example: 4
schema:
type: integer
- name: start_date
required: true
in: path
description: 'Начало периода'
example: '2023-10-29'
schema:
type: string
- name: end_date
required: true
in: path
description: 'Конец периода'
example: '2023-11-13'
schema:
type: string
responses:
'200':
content:
application/json:
schema:
type: object
properties:
Информация для сервиса:
type: string
description: 'Название сервиса'
example: 'Fourth'
Service level agreement(в процентах):
type: integer
description: 'SLA'
example: '96.913'
Общее время недоступности сервиса:
type: string
description: 'Общее время недоступности'
example: '0 месяцев, 1 дней, 10 часов, 12 минут, 31 секунд'
description: ''
tags:
- Service level agreement

components:
schemas:
Services:
type: object
properties:
id:
type: integer
readOnly: true
example: '1'
name:
type: string
maxLength: 100
description: 'Название'
example: 'СAPI2'
status:
type: string
maxLength: 50
description: 'Состояние'
example: 'работает'
description:
type: string
description: 'Описание'
example: 'Крутой сервис'
Service:
type: object
properties:
id:
title: ID
type: integer
readOnly: true
example: 2
name:
title: Название сервиса
type: string
example: "Крутой сервис"
maxLength: 100
status:
title: Статус работы сервиса
type: string
example: "работает"
description:
title: Опсиание сервиса
type: string
example: "Описание крутого сервиса"
History:
type: object
properties:
id:
title: ID
type: integer
readOnly: true
example: 1
name:
title: Название сервиса
type: string
example: "CAPI2"
maxLength: 100
service_id:
title: ID сервиса
type: string
example: 3
status:
title: Статус работы сервиса
type: string
example: "работает"
last_modified:
title: Дата последнего изменения работы сервиса
type: string
example: "12.11.2023 12:05:52"
2 changes: 2 additions & 0 deletions infra/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DEBUG=True
ALLOWED_HOSTS=127.0.0.1
24 changes: 24 additions & 0 deletions infra/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3.8'

services:
web:
build: ../services/
restart: always
volumes:
- static_value:/app/static/
env_file:
- .env

nginx:
image: nginx:1.21.3-alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ../services/api/docs/:/usr/share/nginx/html/api/docs/
- static_value:/var/html/static/
depends_on:
- web

volumes:
static_value:
Loading