Pylint 7.5
This commit is contained in:
parent
3f6cf23f4e
commit
8e0610840d
@ -148,7 +148,10 @@ docker run -d -p 8000:8000 \
|
||||
Пример полной конфигурации можно найти в [.env.example](.env.example). Почту и токен админа ZenDesk взять у руководителя (если вы не админ).
|
||||
|
||||
## Для проверки pylint используем:
|
||||
pylint --load-plugins pylint_django ../access_controller
|
||||
pylint --load-plugins pylint_django --disable=E5110,C0415 ../access_controller
|
||||
|
||||
## Для приведения файлов к стандарту PEP8 используем:
|
||||
autopep8 --in-place <filename>
|
||||
|
||||
## Read more
|
||||
- Zenpy: [http://docs.facetoe.com.au](http://docs.facetoe.com.au)
|
||||
|
@ -1,5 +1,11 @@
|
||||
"""
|
||||
Стандартный файл Django конфигурации приложения.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MainConfig(AppConfig):
|
||||
"""
|
||||
Старт приложения
|
||||
"""
|
||||
name = 'main'
|
||||
|
@ -38,7 +38,8 @@ def make_engineer(user_profile: UserProfile, who_changes: User) -> None:
|
||||
Функция устанавливает пользователю роль инженера.
|
||||
|
||||
:param user_profile: Профиль пользователя
|
||||
:return: Вызов функции **update_role** с параметрами: профиль пользователя, роль "engineer"
|
||||
:return: Вызов функции **update_role** с параметрами:
|
||||
профиль пользователя, роль "engineer"
|
||||
"""
|
||||
update_role(user_profile, ROLES['engineer'])
|
||||
|
||||
@ -48,7 +49,8 @@ def make_light_agent(user_profile: UserProfile) -> None:
|
||||
Функция устанавливает пользователю роль легкого агента.
|
||||
|
||||
:param user_profile: Профиль пользователя
|
||||
:return: Вызов функции **update_role** с параметрами: профиль пользователя, роль "light_agent"
|
||||
:return: Вызов функции **update_role** с параметрами:
|
||||
профиль пользователя, роль "light_agent"
|
||||
"""
|
||||
tickets = get_tickets_list(user_profile.user.email)
|
||||
ticket: ZenpyTicket
|
||||
@ -56,7 +58,8 @@ def make_light_agent(user_profile: UserProfile) -> None:
|
||||
UnassignedTicket.objects.create(
|
||||
assignee=user_profile.user,
|
||||
ticket_id=ticket.id,
|
||||
status=UnassignedTicketStatus.SOLVED if ticket.status == 'solved' else UnassignedTicketStatus.UNASSIGNED
|
||||
status=UnassignedTicketStatus.SOLVED if ticket.status == 'solved'
|
||||
else UnassignedTicketStatus.UNASSIGNED
|
||||
)
|
||||
if ticket.status == 'solved':
|
||||
ticket.assignee_id = zenpy.solved_tickets_user_id
|
||||
@ -79,7 +82,8 @@ def make_light_agent(user_profile: UserProfile) -> None:
|
||||
|
||||
def get_users_list() -> list:
|
||||
"""
|
||||
Функция **get_users_list** возвращает список пользователей Zendesk, относящихся к организации SYSTEM.
|
||||
Функция **get_users_list** возвращает список
|
||||
пользователей Zendesk, относящихся к организации SYSTEM.
|
||||
"""
|
||||
zendesk = zenpy
|
||||
|
||||
@ -101,7 +105,8 @@ def update_profile(user_profile: UserProfile) -> None:
|
||||
Функция обновляет профиль пользователя в соответствии с текущим в Zendesk.
|
||||
|
||||
:param user_profile: Профиль пользователя
|
||||
:return: Обновленный, в соответствие с текущими данными в Zendesk, профиль пользователя
|
||||
:return: Обновленный, в соответствие с текущими данными
|
||||
в Zendesk, профиль пользователя
|
||||
"""
|
||||
user = zenpy.get_user(user_profile.user.email)
|
||||
user_profile.name = user.name
|
||||
@ -135,7 +140,8 @@ def check_user_auth(email: str, password: str) -> bool:
|
||||
"""
|
||||
Функция проверяет, верны ли входные данные.
|
||||
|
||||
:raise: :class:`APIException`: исключение, вызываемое если пользователь не аутентифицирован
|
||||
:raise: :class:`APIException`: исключение,
|
||||
вызываемое если пользователь не аутентифицирован
|
||||
"""
|
||||
creds = {
|
||||
'email': email,
|
||||
@ -207,10 +213,12 @@ def daterange(start_date: timedelta, end_date: timedelta) -> list:
|
||||
return dates
|
||||
|
||||
|
||||
def get_timedelta(log: RoleChangeLogs, time: timedelta=None) -> timedelta:
|
||||
def get_timedelta(log: RoleChangeLogs, time: timedelta = None) -> timedelta:
|
||||
"""
|
||||
Функция возвращает объект класса timedelta, который хранит промежуток времени от начала суток до момента,
|
||||
который находится в log (объект класса RoleChangeLogs) или в time(datetime.time), если введён.
|
||||
Функция возвращает объект класса timedelta,
|
||||
который хранит промежуток времени от начала суток до момента,
|
||||
который находится в log (объект класса RoleChangeLogs)
|
||||
или в time(datetime.time), если введён.
|
||||
|
||||
:param log: Лог
|
||||
:param time: Время
|
||||
@ -278,7 +286,9 @@ class StatisticData:
|
||||
"""
|
||||
Функция возвращает статистику работы пользователя.
|
||||
|
||||
:return: Словарь statistic с применением формата отображения и интервала работы(если они есть). None, если были ошибки при создании.
|
||||
:return: Словарь statistic с применением формата отображения
|
||||
и интервала работы(если они есть).
|
||||
None, если были ошибки при создании.
|
||||
"""
|
||||
if self.is_valid_statistic():
|
||||
stat = self.statistic
|
||||
@ -369,9 +379,12 @@ class StatisticData:
|
||||
if self.interval == 'months':
|
||||
# Переделываем ключи под формат('начало_месяца - конец_месяца')
|
||||
for key, value in stat.items():
|
||||
current_month_start = max(self.start_date, date(year=key.year, month=key.month, day=1))
|
||||
current_month_end = min(self.end_date, last_day_of_month(date(year=key.year, month=key.month, day=1)))
|
||||
index = ' - '.join([str(current_month_start), str(current_month_end)])
|
||||
current_month_start = max(self.start_date, date(
|
||||
year=key.year, month=key.month, day=1))
|
||||
current_month_end = min(self.end_date, last_day_of_month(
|
||||
date(year=key.year, month=key.month, day=1)))
|
||||
index = ' - '.join([str(current_month_start),
|
||||
str(current_month_end)])
|
||||
if new_stat.get(index):
|
||||
new_stat[index] += value
|
||||
else:
|
||||
@ -392,16 +405,20 @@ class StatisticData:
|
||||
|
||||
def _init_data(self) -> None:
|
||||
"""
|
||||
Функция возвращает логи в диапазоне дат start_date - end_date для пользователя с указанным email.
|
||||
Функция возвращает логи в диапазоне дат
|
||||
start_date - end_date для пользователя с указанным email.
|
||||
|
||||
:return: Данные о смене статусов пользователя. Если пользователь не найден или интервал времени некорректен - ошибку.
|
||||
:return: Данные о смене статусов пользователя.
|
||||
Если пользователь не найден или интервал времени некорректен - ошибку.
|
||||
"""
|
||||
if not self.check_time():
|
||||
self.errors += ['Конец диапазона должен быть позже начала диапазона и раньше текущего времени']
|
||||
self.errors += [
|
||||
'Конец диапазона должен быть позже начала диапазона и раньше текущего времени']
|
||||
return
|
||||
try:
|
||||
self.data = RoleChangeLogs.objects.filter(
|
||||
change_time__range=[self.start_date, self.end_date + timedelta(days=1)],
|
||||
change_time__range=[self.start_date,
|
||||
self.end_date + timedelta(days=1)],
|
||||
user=User.objects.get(email=self.email),
|
||||
).order_by('change_time')
|
||||
except User.DoesNotExist:
|
||||
@ -409,7 +426,8 @@ class StatisticData:
|
||||
|
||||
def _init_statistic(self) -> None:
|
||||
"""
|
||||
Функция заполняет словарь, в котором ключ - дата, значение - кол-во проработанных в этот день секунд.
|
||||
Функция заполняет словарь, в котором ключ - дата,
|
||||
значение - кол-во проработанных в этот день секунд.
|
||||
|
||||
:return: Статистика работы пользователя (statistic)
|
||||
"""
|
||||
@ -439,11 +457,14 @@ class StatisticData:
|
||||
if current_log.change_time.date() != next_log.change_time.date():
|
||||
self.statistic[current_log.change_time.date()] += (
|
||||
timedelta(days=1) - get_timedelta(current_log)).total_seconds()
|
||||
self.statistic[next_log.change_time.date()] += get_timedelta(next_log).total_seconds()
|
||||
self.fill_daterange(current_log.change_time.date() + timedelta(days=1), next_log.change_time.date())
|
||||
self.statistic[next_log.change_time.date(
|
||||
)] += get_timedelta(next_log).total_seconds()
|
||||
self.fill_daterange(current_log.change_time.date(
|
||||
) + timedelta(days=1), next_log.change_time.date())
|
||||
else:
|
||||
elapsed_time = next_log.change_time - current_log.change_time
|
||||
self.statistic[current_log.change_time.date()] += elapsed_time.total_seconds()
|
||||
self.statistic[current_log.change_time.date(
|
||||
)] += elapsed_time.total_seconds()
|
||||
|
||||
def post_engineer_logic(self, last_log: RoleChangeLogs) -> None:
|
||||
"""
|
||||
@ -451,16 +472,19 @@ class StatisticData:
|
||||
|
||||
:param last_log: Последний лог
|
||||
"""
|
||||
self.fill_daterange(last_log.change_time.date() + timedelta(days=1), self.end_date + timedelta(days=1))
|
||||
self.fill_daterange(last_log.change_time.date(
|
||||
) + timedelta(days=1), self.end_date + timedelta(days=1))
|
||||
if last_log.change_time.date() == timezone.now().date():
|
||||
self.statistic[last_log.change_time.date()] += (
|
||||
get_timedelta(None, timezone.now().time()) - get_timedelta(last_log)
|
||||
get_timedelta(None, timezone.now().time()) -
|
||||
get_timedelta(last_log)
|
||||
).total_seconds()
|
||||
else:
|
||||
self.statistic[last_log.change_time.date()] += (
|
||||
timedelta(days=1) - get_timedelta(last_log)).total_seconds()
|
||||
if self.end_date == timezone.now().date():
|
||||
self.statistic[self.end_date] = get_timedelta(None, timezone.now().time()).total_seconds()
|
||||
self.statistic[self.end_date] = get_timedelta(
|
||||
None, timezone.now().time()).total_seconds()
|
||||
|
||||
def prev_engineer_logic(self, first_log: RoleChangeLogs) -> None:
|
||||
"""
|
||||
@ -470,7 +494,8 @@ class StatisticData:
|
||||
"""
|
||||
self.fill_daterange(max(User.objects.get(email=self.email).date_joined.date(), self.start_date),
|
||||
first_log.change_time.date())
|
||||
self.statistic[first_log.change_time.date()] += get_timedelta(first_log).total_seconds()
|
||||
self.statistic[first_log.change_time.date(
|
||||
)] += get_timedelta(first_log).total_seconds()
|
||||
|
||||
def fill_daterange(self, first: date, last: date, val: int = 24 * 3600) -> None:
|
||||
"""
|
||||
@ -488,7 +513,8 @@ class StatisticData:
|
||||
Функция осуществляет обновление всех дней.
|
||||
"""
|
||||
self.statistic.clear()
|
||||
self.fill_daterange(self.start_date, self.end_date + timedelta(days=1), 0)
|
||||
self.fill_daterange(
|
||||
self.start_date, self.end_date + timedelta(days=1), 0)
|
||||
|
||||
|
||||
class DatabaseHandler(logging.Handler):
|
||||
@ -571,9 +597,10 @@ def log(user: User, admin: int = 0) -> None:
|
||||
|
||||
|
||||
def set_session_params_for_work_page(request: WSGIRequest, count: int = None, is_confirm: bool = True) -> \
|
||||
Union[HttpResponsePermanentRedirect, HttpResponseRedirect]:
|
||||
Union[HttpResponsePermanentRedirect, HttpResponseRedirect]:
|
||||
"""
|
||||
Функция для страницы получения прав, устанавливает данные сессии о успешности запроса и количестве назначенных тикетов.
|
||||
Функция для страницы получения прав, устанавливает данные сессии
|
||||
о успешности запроса и количестве назначенных тикетов.
|
||||
|
||||
:param request: Получение данных с рабочей страницы пользователя
|
||||
:param count: Количество запрошенных тикетов
|
||||
|
@ -66,8 +66,7 @@ class CustomAuthenticationForm(AuthenticationForm):
|
||||
error_messages = {
|
||||
'invalid_login':
|
||||
"Пожалуйста, введите правильные электронную почту и пароль. Оба поля "
|
||||
"могут быть чувствительны к регистру."
|
||||
,
|
||||
"могут быть чувствительны к регистру.",
|
||||
'inactive': "Аккаунт не активен.",
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,15 @@ class UserProfile(models.Model):
|
||||
('has_control_access', 'Can view admin page'),
|
||||
)
|
||||
|
||||
user = models.OneToOneField(to=User, on_delete=models.CASCADE, help_text='Пользователь')
|
||||
role = models.CharField(default='None', max_length=100, help_text='Глобальное имя роли пользователя')
|
||||
custom_role_id = models.IntegerField(default=0, help_text='Код роли пользователя')
|
||||
user = models.OneToOneField(
|
||||
to=User, on_delete=models.CASCADE, help_text='Пользователь')
|
||||
role = models.CharField(default='None', max_length=100,
|
||||
help_text='Глобальное имя роли пользователя')
|
||||
custom_role_id = models.IntegerField(
|
||||
default=0, help_text='Код роли пользователя')
|
||||
image = models.URLField(null=True, blank=True, help_text='Аватарка')
|
||||
name = models.CharField(default='None', max_length=100, help_text='Имя пользователя на нашем сайте')
|
||||
name = models.CharField(default='None', max_length=100,
|
||||
help_text='Имя пользователя на нашем сайте')
|
||||
|
||||
@property
|
||||
def zendesk_role(self):
|
||||
@ -49,12 +53,16 @@ class RoleChangeLogs(models.Model):
|
||||
"""
|
||||
Модель для логирования изменений ролей пользователя.
|
||||
"""
|
||||
user = models.ForeignKey(to=User, on_delete=models.CASCADE,
|
||||
user = models.ForeignKey(to=User,
|
||||
on_delete=models.CASCADE,
|
||||
help_text='Пользователь, которому присвоили другую роль')
|
||||
old_role = models.IntegerField(default=0, help_text='Старая роль')
|
||||
new_role = models.IntegerField(default=0, help_text='Присвоенная роль')
|
||||
change_time = models.DateTimeField(default=timezone.now, help_text='Дата и время изменения роли')
|
||||
changed_by = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='changed_by',
|
||||
change_time = models.DateTimeField(
|
||||
default=timezone.now, help_text='Дата и время изменения роли')
|
||||
changed_by = models.ForeignKey(to=User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='changed_by',
|
||||
help_text='Кем была изменена роль')
|
||||
|
||||
|
||||
@ -64,13 +72,15 @@ class UnassignedTicketStatus(models.IntegerChoices):
|
||||
|
||||
:param UNASSIGNED: Снят с пользователя, перенесён в буферную группу
|
||||
:param RESTORED: Авторство восстановлено
|
||||
:param NOT_FOUND: Пока нас не было, тикет испарился из буферной группы. Дополнительные действия не требуются
|
||||
:param NOT_FOUND: Пока нас не было, тикет испарился из буферной группы.
|
||||
Дополнительные действия не требуются
|
||||
:param CLOSED: Тикет уже был закрыт. Дополнительные действия не требуются
|
||||
:param SOLVED: Тикет решён. Записан на пользователя с почтой SOLVED_TICKETS_EMAIL
|
||||
"""
|
||||
UNASSIGNED = 0, 'Снят с пользователя, перенесён в буферную группу'
|
||||
RESTORED = 1, 'Авторство восстановлено'
|
||||
NOT_FOUND = 2, 'Пока нас не было, тикет испарился из буферной группы. Дополнительные действия не требуются'
|
||||
NOT_FOUND = 2, 'Пока нас не было, тикет испарился из ' \
|
||||
'буферной группы. Дополнительные действия не требуются'
|
||||
CLOSED = 3, 'Тикет уже был закрыт. Дополнительные действия не требуются'
|
||||
SOLVED = 4, 'Тикет решён. Записан на пользователя с почтой SOLVED_TICKETS_EMAIL'
|
||||
|
||||
@ -79,6 +89,11 @@ class UnassignedTicket(models.Model):
|
||||
"""
|
||||
Модель не распределенного тикета.
|
||||
"""
|
||||
assignee = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='tickets', help_text='Пользователь, с которого снят тикет')
|
||||
ticket_id = models.IntegerField(help_text='Номер тикера, для которого сняли ответственного')
|
||||
status = models.IntegerField(choices=UnassignedTicketStatus.choices, default=UnassignedTicketStatus.UNASSIGNED, help_text='Статус тикета')
|
||||
assignee = models.ForeignKey(to=User, on_delete=models.CASCADE,
|
||||
related_name='tickets',
|
||||
help_text='Пользователь, с которого снят тикет')
|
||||
ticket_id = models.IntegerField(
|
||||
help_text='Номер тикера, для которого сняли ответственного')
|
||||
status = models.IntegerField(choices=UnassignedTicketStatus.choices,
|
||||
default=UnassignedTicketStatus.UNASSIGNED,
|
||||
help_text='Статус тикета')
|
||||
|
@ -1,3 +1,7 @@
|
||||
"""
|
||||
Основной функционал приложения.
|
||||
"""
|
||||
|
||||
from smtplib import SMTPException
|
||||
from typing import Dict, Any
|
||||
|
||||
@ -117,7 +121,8 @@ class CustomRegistrationView(RegistrationView):
|
||||
@staticmethod
|
||||
def set_permission(user: User) -> None:
|
||||
"""
|
||||
Функция дает разрешение на просмотр страница администратора, если пользователь имеет роль admin.
|
||||
Функция дает разрешение на просмотр страница администратора,
|
||||
если пользователь имеет роль admin.
|
||||
|
||||
:param user: авторизованный пользователь (получает разрешение, имея роль "admin")
|
||||
"""
|
||||
@ -131,7 +136,8 @@ class CustomRegistrationView(RegistrationView):
|
||||
|
||||
def get_success_url(self, user: User = None) -> Dict:
|
||||
"""
|
||||
Функция возвращает url-адрес страницы, куда нужно перейти после успешной/не успешной регистрации.
|
||||
Функция возвращает url-адрес страницы, куда нужно перейти после
|
||||
успешной/не успешной регистрации.
|
||||
Используется самой django-registration.
|
||||
|
||||
:param user: пользователь, пытающийся зарегистрироваться
|
||||
@ -172,11 +178,13 @@ def profile_page(request: WSGIRequest) -> HttpResponse:
|
||||
@login_required()
|
||||
def work_page(request: WSGIRequest, id: int) -> HttpResponse:
|
||||
"""
|
||||
Функция отображения страницы "Управления правами" для текущего пользователя (login_required).
|
||||
Функция отображения страницы "Управления правами"
|
||||
для текущего пользователя (login_required).
|
||||
|
||||
:param request: объект пользователя
|
||||
:param id: id пользователя, используется для динамической адресации
|
||||
:return: адресация на страницу "Управления правами" (либо на страницу "Авторизации", если id и user.id не совпадают
|
||||
:return: адресация на страницу "Управления правами"
|
||||
(либо на страницу "Авторизации", если id и user.id не совпадают)
|
||||
"""
|
||||
users = get_users_list()
|
||||
if request.user.id == id:
|
||||
@ -212,7 +220,8 @@ def work_page(request: WSGIRequest, id: int) -> HttpResponse:
|
||||
@login_required()
|
||||
def work_hand_over(request: WSGIRequest) -> HttpResponseRedirect:
|
||||
"""
|
||||
Функция позволяет текущему пользователю сдать права, а именно сменить в Zendesk роль с "engineer" на "light_agent"
|
||||
Функция позволяет текущему пользователю сдать права,
|
||||
а именно сменить в Zendesk роль с "engineer" на "light_agent"
|
||||
|
||||
:param request: данные текущего пользователя (login_required)
|
||||
:return: перезагрузка текущей страницы после выполнения смены роли
|
||||
@ -224,7 +233,9 @@ def work_hand_over(request: WSGIRequest) -> HttpResponseRedirect:
|
||||
@login_required()
|
||||
def work_become_engineer(request: WSGIRequest) -> HttpResponseRedirect:
|
||||
"""
|
||||
Функция позволяет текущему пользователю получить права, а именно сменить в Zendesk роль с "light_agent" на "engineer"
|
||||
Функция позволяет текущему пользователю получить права,
|
||||
а именно сменить в Zendesk роль с "light_agent" на
|
||||
"engineer"
|
||||
|
||||
:param request: данные текущего пользователя (login_required)
|
||||
:return: перезагрузка текущей страницы после выполнения смены роли
|
||||
@ -371,7 +382,8 @@ def statistic_page(request: WSGIRequest) -> HttpResponse:
|
||||
"""
|
||||
Функция отображения страницы статистики (для "superuser").
|
||||
|
||||
:param request: данные о пользователе: email, время и интервал работы. Данные получаем через forms.StatisticForm
|
||||
:param request: данные о пользователе: email, время и интервал работы.
|
||||
Данные получаем через forms.StatisticForm
|
||||
:return: адресация на страницу статистики
|
||||
"""
|
||||
|
||||
|
@ -17,3 +17,4 @@ sphinxcontrib-spelling==7.1.0
|
||||
m2r == 0.2.1
|
||||
pylint == 2.8.2
|
||||
pylint-django == 2.4.4
|
||||
autopep8 = 1.5.6
|
||||
|
Loading…
x
Reference in New Issue
Block a user