Merged develop into current

This commit is contained in:
Timofey Mazurov 2021-03-15 19:09:45 +03:00
commit 46012f487b
14 changed files with 447 additions and 40 deletions

View File

@ -135,7 +135,6 @@ ACCOUNT_ACTIVATION_DAYS = 7
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/'
# Название_приложения.Названиеайла.Название_класса_обработчика # Название_приложения.Названиеайла.Название_класса_обработчика
AUTHENTICATION_BACKENDS = [ AUTHENTICATION_BACKENDS = [
'access_controller.auth.EmailAuthBackend', 'access_controller.auth.EmailAuthBackend',
@ -149,3 +148,5 @@ ZENDESK_ROLES = {
'engineer': 360005209000, 'engineer': 360005209000,
'light_agent': 360005208980, 'light_agent': 360005208980,
} }
ONE_DAY = 12 # Количество часов в 1 рабочем дне

View File

@ -19,6 +19,8 @@ from django.urls import path, include
from main.views import work_page, work_hand_over, work_become_engineer, AdminPageView from main.views import work_page, work_hand_over, work_become_engineer, AdminPageView
from main.views import main_page, profile_page, CustomRegistrationView, CustomLoginView from main.views import main_page, profile_page, CustomRegistrationView, CustomLoginView
from main.views import work_page, work_hand_over, work_become_engineer, \
AdminPageView, statistic_page
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls, name='admin'), path('admin/', admin.site.urls, name='admin'),
@ -31,9 +33,8 @@ urlpatterns = [
path('work/<int:id>', work_page, name="work"), path('work/<int:id>', work_page, name="work"),
path('work/hand_over/', work_hand_over, name="work_hand_over"), path('work/hand_over/', work_hand_over, name="work_hand_over"),
path('work/become_engineer/', work_become_engineer, name="work_become_engineer"), path('work/become_engineer/', work_become_engineer, name="work_become_engineer"),
path('accounts/', include('django_registration.backends.activation.urls')), path('control/', AdminPageView.as_view(), name='control'),
path('accounts/login/', include('django.contrib.auth.urls')), path('statistic/', statistic_page, name='statistic')
path('control/', AdminPageView.as_view(), name='control')
] ]
urlpatterns += [ urlpatterns += [

View File

@ -1,17 +1,15 @@
import logging import logging
import os import os
from datetime import timedelta, datetime, date
from django.contrib.auth.models import User
from django.utils import timezone from django.utils import timezone
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 main.models import UserProfile, RoleChangeLogs from main.models import UserProfile, RoleChangeLogs
from access_controller.settings import ZENDESK_ROLES as ROLES
# from access_controller.main.models import RoleChangeLogs
class ZendeskAdmin: class ZendeskAdmin:
""" """
@ -77,7 +75,7 @@ class ZendeskAdmin:
user = self.admin.users.search(email).values[0] user = self.admin.users.search(email).values[0]
return user.photo['content_url'] if user.photo else None return user.photo['content_url'] if user.photo else None
def get_user(self, email: str) -> str: def get_user(self, email: str):
""" """
Функция **get_user** возвращает пользователя (объект) по его email Функция **get_user** возвращает пользователя (объект) по его email
@ -91,7 +89,7 @@ class ZendeskAdmin:
Функция **get_user_org** возвращает организацию, к которой относится пользователь по его email Функция **get_user_org** возвращает организацию, к которой относится пользователь по его email
""" """
user = self.admin.users.search(email).values[0] user = self.admin.users.search(email).values[0]
return user.organization.name return user.organization.name if user.organization else None
def create_admin(self) -> Zenpy: def create_admin(self) -> Zenpy:
""" """
@ -105,7 +103,7 @@ class ZendeskAdmin:
if self.email is None: if self.email is None:
raise ValueError('access_controller email not in env') raise ValueError('access_controller email not in env')
self.credentials['email'] = os.getenv('ACCESS_CONTROLLER_API_EMAIL') self.credentials['email'] = self.email
if self.token: if self.token:
self.credentials['token'] = self.token self.credentials['token'] = self.token
@ -161,6 +159,7 @@ def update_profile(user_profile: UserProfile) -> UserProfile:
user = ZendeskAdmin().get_user(user_profile.user.email) user = ZendeskAdmin().get_user(user_profile.user.email)
user_profile.name = user.name user_profile.name = user.name
user_profile.role = user.role user_profile.role = user.role
user_profile.custom_role_id = user.custom_role_id if user.custom_role_id else 0
user_profile.image = user.photo['content_url'] if user.photo else None user_profile.image = user.photo['content_url'] if user.photo else None
user_profile.save() user_profile.save()
@ -179,24 +178,213 @@ def get_user_organization(email: str) -> str:
return ZendeskAdmin().get_user_org(email) return ZendeskAdmin().get_user_org(email)
def check_user_auth(email: str, password: str) -> bool: def daterange(start_date, end_date) -> list:
""" """
Функция проверяет, верны ли входные данные Возвращает список дней с start_date по end_date исключая правую границу
"""
dates = []
for n in range(int((end_date - start_date).days)):
dates.append(start_date + timedelta(n))
return dates
:raise: :class:`APIException`: исключение, вызываемое если пользователь не аутентифицирован
def get_timedelta(log, time=None) -> timedelta:
""" """
creds = { Возвращает объект класса timedelta, который хранит промежуток времени от начала суток до момента,
'email': email, который находится в log (объект класса RoleChangeLogs) или в time(datetime.time), если введён
'password': password, """
'subdomain': 'ngenix1612197338', if time is None:
} time = log.change_time.time()
try: time = timedelta(hours=time.hour, minutes=time.minute, seconds=time.second)
user = Zenpy(**creds) return time
user.search(email, type='user')
except APIException:
def last_day_of_month(day):
"""
Возвращает последний день любого месяца
"""
next_month = day.replace(day=28) + timedelta(days=4)
return next_month - timedelta(days=next_month.day)
class StatisticData:
def __init__(self, start_date, end_date, user_email, stat=None):
self.display = None
self.interval = None
self.start_date = start_date
self.end_date = end_date
self.email = user_email
self.errors = list()
self.warnings = list()
self.data = dict()
self.statistic = dict()
self._set_data()
if stat is None:
self._set_statistic()
else:
self.statistic = stat
def get_statistic(self):
"""
Вернуть словарь statistic с применением формата отображения и интеравала работы(если они есть)
None, если были ошибки при создании
"""
if self.is_valid_statistic():
stat = self.statistic
stat = self._use_display(stat)
stat = self._use_interval(stat)
return stat
else:
return None
def is_valid_statistic(self):
"""
Были ли ошибки при создании статистики
"""
return not self.errors and self.statistic
def set_interval(self, interval):
"""
Устанавливает интервал работы
"""
if interval not in ['months', 'days']:
self.errors += ['Интервал работы должен быть в днях или месяцах']
return False
self.interval = interval
return True
def set_display(self, display_format):
"""
Устанавливает формат отображения
"""
if display_format not in ['days', 'hours']:
self.errors += ['Формат отображения должен быть в часах или днях']
return False
self.display = display_format
return True
def get_data(self):
"""
Вернуть данные
data - массив объектов RoleChangeLogs, является списком логов пользователя
data может быть пустым списком
"""
if self.is_valid_data():
return self.data
else:
return None
def is_valid_data(self):
"""
Были ли ошибки при получении логов
"""
return not self.errors
def _use_display(self, stat):
"""
Приводит данные к формату отображения
"""
if not self.is_valid_statistic() or not self.display:
return stat
new_stat = {}
for key, item in stat.items():
if self.display == 'hours':
new_stat[key] = item / 3600
elif self.display == 'days':
new_stat[key] = item / (ONE_DAY * 3600)
return new_stat
def _use_interval(self, stat):
"""
Объединяет ключи и значения в соответствии с интервалом работы
"""
if not self.is_valid_statistic() or not self.interval:
return stat
new_stat = {}
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)])
if new_stat.get(index):
new_stat[index] += value
else:
new_stat[index] = value
elif self.interval == 'days':
new_stat = stat # статистика изначально в днях
return new_stat
def check_time(self):
"""
Проверка на правильность введенного времени
"""
if self.end_date < self.start_date or self.end_date > datetime.now().date():
return False return False
return True return True
def _set_data(self):
"""
Получение логов в диапазоне дат start_date-end_date для пользователя с почтой email
"""
if not self.check_time():
self.errors += ['Конец диапазона должен быть позже начала диапазона и раньше текущего времени']
return
try:
self.data = RoleChangeLogs.objects.filter(
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:
self.errors += ['Пользователь не найден']
def _set_statistic(self):
"""
Функция заполняет словарь, в котором ключ - дата, значение - кол-во проработанных в этот день секунд
"""
self.clear_statistic()
if not self.get_data():
self.warnings += ['Не обнаружены изменения роли в данном промежутке']
return None
first_log, last_log = self.data[0], self.data[len(self.data) - 1]
if first_log.old_role == ROLES['engineer']:
self.fill_daterange(self.start_date, first_log.change_time.date())
self.statistic[first_log.change_time.date()] += get_timedelta(first_log).total_seconds()
if last_log.new_role == ROLES['engineer']:
self.fill_daterange(last_log.change_time.date() + timedelta(days=1), self.end_date + timedelta(days=1))
self.statistic[last_log.change_time.date()] += (timedelta(days=1) - get_timedelta(last_log)).total_seconds()
if self.end_date == datetime.now().date():
self.statistic[self.end_date] = get_timedelta(None, datetime.now().time()).total_seconds()
for log_index in range(len(self.data) - 1):
if self.data[log_index].new_role == ROLES['engineer']:
current_log, next_log = self.data[log_index], self.data[log_index + 1]
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())
else:
elapsed_time = next_log.change_time - current_log.change_time
self.statistic[current_log.change_time.date()] += elapsed_time.total_seconds()
def fill_daterange(self, first, last, val=24 * 3600):
"""
Заполение диапазона дат значением val
по умолчанию val = кол-во секунд в 1 дне
"""
for day in daterange(first, last):
self.statistic[day] = val
def clear_statistic(self):
"""
Обнуление всех дней
"""
self.statistic.clear()
self.fill_daterange(self.start_date, self.end_date + timedelta(days=1), 0)
class DatabaseHandler(logging.Handler): class DatabaseHandler(logging.Handler):
def __init__(self): def __init__(self):

View File

@ -2,6 +2,7 @@ from django import forms
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django_registration.forms import RegistrationFormUniqueEmail from django_registration.forms import RegistrationFormUniqueEmail
from access_controller.settings import ZENDESK_ROLES
from main.models import UserProfile from main.models import UserProfile
@ -14,7 +15,6 @@ class CustomRegistrationForm(RegistrationFormUniqueEmail):
:param visible_fields.email: Поле для ввода email, зарегистирированного на Zendesk :param visible_fields.email: Поле для ввода email, зарегистирированного на Zendesk
:type visible_fields.email: :class:`django_registration.forms.RegistrationFormUniqueEmail` :type visible_fields.email: :class:`django_registration.forms.RegistrationFormUniqueEmail`
""" """
def __init__(self, *args, **kwargs) -> RegistrationFormUniqueEmail: def __init__(self, *args, **kwargs) -> RegistrationFormUniqueEmail:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
for visible in self.visible_fields(): for visible in self.visible_fields():
@ -23,7 +23,7 @@ class CustomRegistrationForm(RegistrationFormUniqueEmail):
visible.field.widget.attrs['class'] += 'form-control' visible.field.widget.attrs['class'] += 'form-control'
else: else:
visible.field.widget.attrs['class'] = 'form-control' visible.field.widget.attrs['class'] = 'form-control'
if visible.html_name !='email': if visible.html_name != 'email':
visible.field.required = False visible.field.required = False
class Meta(RegistrationFormUniqueEmail.Meta): class Meta(RegistrationFormUniqueEmail.Meta):
@ -42,7 +42,8 @@ class AdminPageUsers(forms.Form):
queryset=UserProfile.objects.filter(role='agent'), queryset=UserProfile.objects.filter(role='agent'),
widget=forms.CheckboxSelectMultiple( widget=forms.CheckboxSelectMultiple(
attrs={ attrs={
'class': 'form-check-input' 'class': 'form-check-input',
} }
), ),
label='' label=''
@ -65,3 +66,31 @@ class CustomAuthenticationForm(AuthenticationForm):
, ,
'inactive': "Аккаунт не активен.", 'inactive': "Аккаунт не активен.",
} }
class StatisticForm(forms.Form):
email = forms.EmailField(
label='Электроная почта',
)
interval = forms.CharField( # TODO: Переделать под html страницу
label='Интервал работы',
)
display_format = forms.CharField( # TODO: Переделать под html страницу
label='Формат отображения',
)
range_start = forms.DateField( # TODO: Переделать под html страницу
label='Начало диапазона',
widget=forms.DateInput(
attrs={
'type': 'date',
}
),
)
range_end = forms.DateField( # TODO: Переделать под html страницу
label='Конец диапазона',
widget=forms.DateInput(
attrs={
'type': 'date',
}
),
)

View File

@ -0,0 +1,61 @@
# Generated by Django 3.1.6 on 2021-03-11 08:00
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('main', '0008_auto_20210303_2305'),
]
operations = [
migrations.AlterField(
model_name='rolechangelogs',
name='change_time',
field=models.DateTimeField(help_text='Дата и время изменения роли'),
),
migrations.AlterField(
model_name='rolechangelogs',
name='changed_by',
field=models.ForeignKey(help_text='Кем была изменена роль', on_delete=django.db.models.deletion.CASCADE, related_name='changed_by', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='rolechangelogs',
name='name',
field=models.TextField(help_text='Имя пользователя'),
),
migrations.AlterField(
model_name='rolechangelogs',
name='new_role',
field=models.TextField(help_text='Присвоенная роль'),
),
migrations.AlterField(
model_name='rolechangelogs',
name='user',
field=models.ForeignKey(help_text='Пользователь, которому присвоили другую роль', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='userprofile',
name='image',
field=models.URLField(blank=True, help_text='Аватарка', null=True),
),
migrations.AlterField(
model_name='userprofile',
name='name',
field=models.CharField(default='None', help_text='Имя пользователя на нашем сайте', max_length=100),
),
migrations.AlterField(
model_name='userprofile',
name='role',
field=models.CharField(default='None', help_text='Код роли пользователя', max_length=100),
),
migrations.AlterField(
model_name='userprofile',
name='user',
field=models.OneToOneField(help_text='Пользователь', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.1.6 on 2021-03-11 08:04
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('main', '0009_models_help_text'),
]
operations = [
migrations.AlterModelOptions(
name='userprofile',
options={'permissions': (('has_control_access', 'Can view admin page'),)},
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 3.1.6 on 2021-03-11 14:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0010_userprofile_meta'),
]
operations = [
migrations.AddField(
model_name='rolechangelogs',
name='old_role',
field=models.IntegerField(default=0, help_text='Старая роль'),
),
migrations.AlterField(
model_name='rolechangelogs',
name='new_role',
field=models.IntegerField(default=0, help_text='Присвоенная роль'),
),
migrations.AlterField(
model_name='userprofile',
name='role',
field=models.IntegerField(default=0, help_text='Код роли пользователя'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 3.1.6 on 2021-03-12 09:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0011_auto_20210311_1734'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='custom_role_id',
field=models.IntegerField(default=0, help_text='Код роли пользователя'),
),
migrations.AlterField(
model_name='userprofile',
name='role',
field=models.CharField(default='None', help_text='Глобальное имя роли пользователя', max_length=100),
),
]

View File

@ -8,8 +8,14 @@ from django.utils import timezone
class UserProfile(models.Model): class UserProfile(models.Model):
"""Модель профиля пользователя""" """Модель профиля пользователя"""
class Meta:
permissions = (
('has_control_access', 'Can view admin page'),
)
user = models.OneToOneField(to=User, on_delete=models.CASCADE, help_text='Пользователь') user = models.OneToOneField(to=User, on_delete=models.CASCADE, help_text='Пользователь')
role = models.CharField(default='None', max_length=100, 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='Аватарка') 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='Имя пользователя на нашем сайте')
@ -27,8 +33,11 @@ def save_user_profile(sender, instance, **kwargs):
class RoleChangeLogs(models.Model): class RoleChangeLogs(models.Model):
"""Модель для логирования изменений ролей пользователя""" """Модель для логирования изменений ролей пользователя"""
user = models.ForeignKey(to=User, on_delete=models.CASCADE, help_text='Пользователь, которому присвоили другую роль') user = models.ForeignKey(to=User, on_delete=models.CASCADE,
help_text='Пользователь, которому присвоили другую роль')
name = models.TextField(help_text='Имя пользователя') name = models.TextField(help_text='Имя пользователя')
new_role = models.TextField(help_text='Присвоенная роль') old_role = models.IntegerField(default=0, help_text='Старая роль')
new_role = models.IntegerField(default=0, help_text='Присвоенная роль')
change_time = models.DateTimeField(help_text='Дата и время изменения роли', default=timezone.now) change_time = models.DateTimeField(help_text='Дата и время изменения роли', default=timezone.now)
changed_by = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='changed_by', help_text='Кем была изменена роль') changed_by = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='changed_by',
help_text='Кем была изменена роль')

View File

@ -3,10 +3,10 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<nav class="navbar navbar-light" style="background-color: #00FF00;"> <nav class="navbar navbar-light" style="background-color: #113A60;">
<a class="navbar-brand" href="{% url 'index' %}"> <a class="navbar-brand" href="{% url 'index' %}">
<img src="{% static 'main/img/logo.png' %}" width="30" height="30" class="d-inline-block align-top" alt="" loading="lazy"> <img src="{% static 'main/img/logo_real.png' %}" width="107" height="22" class="d-inline-block align-top" alt="" loading="lazy">
Access Controller <t style="color:#FFFFFF">Access Controller</t>
</a> </a>
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<div class="btn-group" role="group" aria-label="Basic example"> <div class="btn-group" role="group" aria-label="Basic example">

View File

@ -10,5 +10,5 @@
{% block content %} {% block content %}
<br> <br>
<h4> Регистрация прошла успешно. <a href="/login/">Войти сейчас</a></h4> <h4> Регистрация прошла успешно. <a href="{% url 'login'%}">Войти сейчас</a></h4>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,49 @@
{% extends 'base/base.html' %}
{% load static %}
{% block title %}{{ pagename }}{% endblock %}
{% block heading %} Пример страницы статистики(палками не бейти плиз){% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'main/css/work.css' %}">
{% endblock %}
{% block content %}
<div>
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
{{field.label}}
{{field}}
<br>
{% endfor %}
<input type="submit">
</form>
<ul>
{% for error in errors %}
<li><span class="badge bg-danger">{{error}}</span></li>
{% endfor %}
</ul>
{%if form.errors%}
<ul>
{% for field, errors in form.errors.items %}
{% for error in errors %}
<li><span class="badge bg-danger">{{error}}</span></li>
{% endfor %}
{% endfor %}
</ul>
{%endif%}
<ul>
{% for warning in warnings %}
<li><span class="badge bg-warning">{{warning}}</span></li>
{% endfor %}
</ul>
{% for key,val in log_stats.items %}
<h3>{{key}} <b>|</b> {{val}}</h3>
<br>
{% endfor %}
</div>
{% endblock %}

View File

@ -14,7 +14,7 @@ from zenpy import Zenpy
from access_controller.settings import EMAIL_HOST_USER from access_controller.settings import EMAIL_HOST_USER
from main.extra_func import check_user_exist, update_profile, get_user_organization, \ from main.extra_func import check_user_exist, update_profile, get_user_organization, \
make_engineer, make_light_agent, get_users_list make_engineer, make_light_agent, get_users_list, log
from django.contrib.auth.models import User, Permission from django.contrib.auth.models import User, Permission
from main.models import UserProfile from main.models import UserProfile
@ -27,7 +27,6 @@ from django.core.exceptions import PermissionDenied
from access_controller.settings import ZENDESK_ROLES from access_controller.settings import ZENDESK_ROLES
from zenpy.lib.api_objects import User as ZenpyUser from zenpy.lib.api_objects import User as ZenpyUser
content_type_temp = ContentType.objects.get_for_model(UserProfile) content_type_temp = ContentType.objects.get_for_model(UserProfile)
permission_temp, created = Permission.objects.get_or_create( permission_temp, created = Permission.objects.get_or_create(
codename='has_control_access', codename='has_control_access',
@ -112,6 +111,7 @@ def profile_page(request: WSGIRequest) -> HttpResponse:
'profile': user_profile, 'profile': user_profile,
'pagename': 'Страница профиля' 'pagename': 'Страница профиля'
} }
log(request.user)
return render(request, 'pages/profile.html', context) return render(request, 'pages/profile.html', context)
@ -151,12 +151,12 @@ def work_page(request, id):
@login_required() @login_required()
def work_hand_over(request): def work_hand_over(request):
zenpy_user, admin = auth_user(request) zenpy_user, admin = auth_user(request)
if zenpy_user.custom_role_id == ZENDESK_ROLES['engineer']: if zenpy_user.custom_role_id == ZENDESK_ROLES['engineer']:
zenpy_user.custom_role_id = ZENDESK_ROLES['light_agent'] zenpy_user.custom_role_id = ZENDESK_ROLES['light_agent']
admin.users.update(zenpy_user) admin.users.update(zenpy_user)
request.user.userprofile.role = "agent" request.user.userprofile.role = "agent"
request.user.userprofile.save() request.user.userprofile.save()
# log(request.user.userprofile.user)
return HttpResponseRedirect(reverse('work', args=(request.user.id,))) return HttpResponseRedirect(reverse('work', args=(request.user.id,)))
@ -168,6 +168,7 @@ def work_become_engineer(request):
admin.users.update(zenpy_user) admin.users.update(zenpy_user)
request.user.userprofile.role = "agent" request.user.userprofile.role = "agent"
request.user.userprofile.save() request.user.userprofile.save()
# log(request.user.userprofile.user)
return HttpResponseRedirect(reverse('work', args=(request.user.id,))) return HttpResponseRedirect(reverse('work', args=(request.user.id,)))

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB