Add ticket unassignment(exclude solved tickets)

This commit is contained in:
Sokurov Idar 2021-03-14 17:13:41 +03:00
parent 1cd8874e03
commit a430ee871d
4 changed files with 59 additions and 50 deletions

View File

@ -183,4 +183,10 @@ ZENDESK_ROLES = {
'light_agent': 360005208980, 'light_agent': 360005208980,
} }
ZENDESK_GROUPS = {
'employees': 'Поддержка',
'buffer': 'Сменная группа',
}
ONE_DAY = 12 # Количество часов в 1 рабочем дне ONE_DAY = 12 # Количество часов в 1 рабочем дне

View File

@ -5,7 +5,7 @@ from django.contrib.auth.models import User
from zenpy import Zenpy from zenpy import Zenpy
from zenpy.lib.exception import APIException from zenpy.lib.exception import APIException
from access_controller.settings import ZENDESK_ROLES as ROLES, ONE_DAY from access_controller.settings import ZENDESK_ROLES as ROLES, ONE_DAY, ZENDESK_GROUPS
from main.models import UserProfile, RoleChangeLogs, UnassignedTicket, UnassignedTicketStatus from main.models import UserProfile, RoleChangeLogs, UnassignedTicket, UnassignedTicketStatus
@ -29,12 +29,6 @@ class ZendeskAdmin:
email: str = os.getenv('ACCESS_CONTROLLER_API_EMAIL') email: str = os.getenv('ACCESS_CONTROLLER_API_EMAIL')
token: str = os.getenv('ACCESS_CONTROLLER_API_TOKEN') token: str = os.getenv('ACCESS_CONTROLLER_API_TOKEN')
password: str = os.getenv('ACCESS_CONTROLLER_API_PASSWORD') password: str = os.getenv('ACCESS_CONTROLLER_API_PASSWORD')
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self): def __init__(self):
self.create_admin() self.create_admin()
@ -82,6 +76,12 @@ class ZendeskAdmin:
""" """
return self.admin.users.search(email).values[0] return self.admin.users.search(email).values[0]
def get_group(self, name):
groups = self.admin.search(name)
for group in groups:
return group
return None
def get_user_org(self, email: str) -> str: def get_user_org(self, email: str) -> str:
""" """
Функция **get_user_org** возвращает организацию, к которой относится пользователь по его email Функция **get_user_org** возвращает организацию, к которой относится пользователь по его email
@ -126,43 +126,42 @@ def update_role(user_profile: UserProfile, role: str) -> UserProfile:
zendesk.admin.users.update(user) zendesk.admin.users.update(user)
def make_engineer(user_profile: UserProfile) -> UserProfile: def make_engineer(user_profile: UserProfile, who_changes: User) -> UserProfile:
""" """
Функция **make_engineer** устанавливает пользователю роль инженера. Функция **make_engineer** устанавливает пользователю роль инженера.
""" """
RoleChangeLogs.objects.create(
user=user_profile.user,
old_role=user_profile.custom_role_id,
new_role=ROLES['engineer'],
changed_by=who_changes
)
update_role(user_profile, ROLES['engineer']) update_role(user_profile, ROLES['engineer'])
def make_light_agent(user_profile: UserProfile, who_changes: User) -> UserProfile: def make_light_agent(user_profile: UserProfile, who_changes: User) -> UserProfile:
""" """
Функция **make_light_agent** устанавливапет пользователю роль легкого агента. Функция **make_light_agent** устанавливапет пользователю роль легкого агента.
.. todo::
Решить проблему с ошибкой при выполнении этой функции из-за неотвязанных тикетов. А именно:
- найти все тикеты, ответственным которых является снимаемый аккаунт
- для всех этих тикетов - перенести ответственность на буферную группу.
- [PARTIALY DONE] создать записи о снятых тикетах и их прошлом авторстве. Если тикет уже был закрыт - выставить в логе CLOSED. Иначе UNASSIGNED
- [DONE] после этого снять права c инженера
- [DONE] создать запись в логе о снятии прав инженера
""" """
tickets = get_ticket_list(user_profile.user.email)
for ticket in tickets:
if ticket.status=='solved':
continue
UnassignedTicket.objects.create(
assignee=user_profile.user,
ticket_id=ticket.id,
status=UnassignedTicketStatus.UNASSIGNED
)
ticket.group = ZendeskAdmin().get_group(ZENDESK_GROUPS['buffer'])
ZendeskAdmin().admin.tickets.update(ticket)
# tickets = [] RoleChangeLogs.objects.create(
# # TODO: set ticket fields correct
# for ticket in tickets:
# UnassignedTicket.create(
# assignee=user_profile.user,
# ticket_id=ticket.number,
# status=UnassignedTicketStatus.UNASSIGNED if ticket.status=='opened' else UnassignedTicketStatus.CLOSED
# )
update_role(user_profile, ROLES['light_agent'])
RoleChangeLogs.create(
user=user_profile.user, user=user_profile.user,
old_role=ROLES['engineer'], old_role=user_profile.custom_role_id,
new_role=ROLES['light_agent'], new_role=ROLES['light_agent'],
changed_by=who_changes changed_by=who_changes
) )
update_role(user_profile, ROLES['light_agent'])
def get_users_list() -> list: def get_users_list() -> list:
@ -175,6 +174,10 @@ def get_users_list() -> list:
return zendesk.admin.organizations.users(org) return zendesk.admin.organizations.users(org)
def get_ticket_list(email):
return ZendeskAdmin().admin.search(assignee=email, type='ticket')
def update_profile(user_profile: UserProfile) -> UserProfile: def update_profile(user_profile: UserProfile) -> UserProfile:
""" """
Функция обновляет профиль пользователя в соотвтетствии с текущим в Zendesk Функция обновляет профиль пользователя в соотвтетствии с текущим в Zendesk
@ -241,9 +244,9 @@ class StatisticData:
self.warnings = list() self.warnings = list()
self.data = dict() self.data = dict()
self.statistic = dict() self.statistic = dict()
self._set_data() self._init_data()
if stat is None: if stat is None:
self._set_statistic() self._init_statistic()
else: else:
self.statistic = stat self.statistic = stat
@ -346,7 +349,7 @@ class StatisticData:
return False return False
return True return True
def _set_data(self): def _init_data(self):
""" """
Получение логов в диапазоне дат start_date-end_date для пользователя с почтой email Получение логов в диапазоне дат start_date-end_date для пользователя с почтой email
""" """
@ -361,7 +364,7 @@ class StatisticData:
except User.DoesNotExist: except User.DoesNotExist:
self.errors += ['Пользователь не найден'] self.errors += ['Пользователь не найден']
def _set_statistic(self): def _init_statistic(self):
""" """
Функция заполняет словарь, в котором ключ - дата, значение - кол-во проработанных в этот день секунд Функция заполняет словарь, в котором ключ - дата, значение - кол-во проработанных в этот день секунд
""" """

View File

@ -1,12 +1,13 @@
# Generated by Django 3.1.6 on 2021-03-12 09:25 # Generated by Django 3.1.6 on 2021-03-14 11:55
from django.db import migrations, models from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('main', '0011_auto_20210311_1734'), ('main', '0013_auto_20210311_2040'),
] ]
operations = [ operations = [
@ -15,6 +16,11 @@ class Migration(migrations.Migration):
name='custom_role_id', name='custom_role_id',
field=models.IntegerField(default=0, help_text='Код роли пользователя'), field=models.IntegerField(default=0, help_text='Код роли пользователя'),
), ),
migrations.AlterField(
model_name='rolechangelogs',
name='change_time',
field=models.DateTimeField(default=django.utils.timezone.now, help_text='Дата и время изменения роли'),
),
migrations.AlterField( migrations.AlterField(
model_name='userprofile', model_name='userprofile',
name='role', name='role',

View File

@ -1,6 +1,5 @@
import logging import logging
import os import os
from datetime import datetime
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.forms import PasswordResetForm
@ -19,11 +18,12 @@ from django_registration.views import RegistrationView
from zenpy import Zenpy from zenpy import Zenpy
from zenpy.lib.api_objects import User as ZenpyUser from zenpy.lib.api_objects import User as ZenpyUser
from access_controller.settings import EMAIL_HOST_USER, ZENDESK_ROLES from access_controller.settings import EMAIL_HOST_USER, ZENDESK_ROLES, ZENDESK_GROUPS
from main.extra_func import check_user_exist, update_profile, get_user_organization, make_engineer, make_light_agent, \ from main.extra_func import check_user_exist, update_profile, get_user_organization, make_engineer, make_light_agent, \
get_users_list, StatisticData get_users_list, StatisticData, get_ticket_list, ZendeskAdmin
from main.forms import AdminPageUsers, CustomRegistrationForm, CustomAuthenticationForm, StatisticForm from main.forms import AdminPageUsers, CustomRegistrationForm, CustomAuthenticationForm, StatisticForm
from .models import UserProfile from .models import UserProfile, UnassignedTicket, UnassignedTicketStatus
class CustomRegistrationView(RegistrationView): class CustomRegistrationView(RegistrationView):
""" """
@ -106,12 +106,7 @@ def profile_page(request: WSGIRequest) -> HttpResponse:
def auth_user(request): def auth_user(request):
admin_creds = { admin = ZendeskAdmin().admin
'email': os.environ.get('ACCESS_CONTROLLER_API_EMAIL'),
'subdomain': 'ngenix1612197338',
'token': os.environ.get('ACCESS_CONTROLLER_API_TOKEN'),
}
admin = Zenpy(**admin_creds)
zenpy_user: ZenpyUser = admin.users.search(request.user.email).values[0] zenpy_user: ZenpyUser = admin.users.search(request.user.email).values[0]
return zenpy_user, admin return zenpy_user, admin
@ -194,7 +189,6 @@ class AdminPageView(LoginRequiredMixin, PermissionRequiredMixin, FormView):
for user in users: for user in users:
make_light_agent(user, self.request.user) make_light_agent(user, self.request.user)
@staticmethod @staticmethod
def count_users(users) -> tuple: def count_users(users) -> tuple:
""" """