diff --git a/main/extra_func.py b/main/extra_func.py
index 8d5abfd..03fd61a 100644
--- a/main/extra_func.py
+++ b/main/extra_func.py
@@ -1,5 +1,5 @@
import os
-from datetime import timedelta
+from datetime import timedelta, datetime
from zenpy import Zenpy
from zenpy.lib.exception import APIException
@@ -194,7 +194,9 @@ def check_user_auth(email: str, password: str) -> bool:
def daterange(start_date, end_date) -> list:
- # Возвращает список дней с start_date по end_date исключая правую границу
+ """
+ Возвращает список дней с start_date по end_date исключая правую границу
+ """
dates = []
for n in range(int((end_date - start_date).days)):
dates.append(start_date + timedelta(n))
@@ -202,8 +204,60 @@ def daterange(start_date, end_date) -> list:
def get_timedelta(log) -> timedelta:
- # Возвращает объект класса timedelta, который хранит промежуток времени от начала суток до момента,
- # который находится в log(RoleChangeLogs)
+ """
+ Возвращает объект класса timedelta, который хранит промежуток времени от начала суток до момента,
+ который находится в log (объект класса RoleChangeLogs)
+ """
time = log.change_time.time()
time = timedelta(hours=time.hour, minutes=time.minute, seconds=time.second)
return time
+
+
+def last_day_of_month(day):
+ """
+ Возвращает последний день любого месяца
+ """
+ next_month = day.replace(day=28) + timedelta(days=4)
+ return next_month - timedelta(days=next_month.day)
+
+
+def get_statistic_from_data(data, start_date, end_date):
+ """
+ Функция возвращает словарь, в котором ключ - дата, значение - кол-во проработанных в этот день секунд
+ data - массив объектов RoleChangeLogs, является списком логов пользователя
+ """
+ if not data:
+ return None
+ # Обнуление всех дней
+ stat = {}
+ for day in daterange(start_date, end_date + timedelta(days=1)):
+ stat[day] = 0
+ first_log, last_log = data[0], data[len(data) - 1]
+
+ # Если инженер работал ещё до начала диапазона
+ if int(first_log.old_role) == ROLES['engineer']:
+ for day in daterange(start_date, first_log.change_time.date()):
+ stat[day] = 24 * 3600
+ stat[first_log.change_time.date()] += get_timedelta(first_log).total_seconds()
+
+ # Если инженер закончил работать после диапазона
+ if int(last_log.new_role) == ROLES['engineer']:
+ for day in daterange(last_log.change_time.date() + timedelta(days=1), end_date + timedelta(days=1)):
+ stat[day] = 24 * 3600
+ stat[last_log.change_time.date()] += (timedelta(days=1)-get_timedelta(last_log)).total_seconds()
+ # Цикл по логам
+ for log_index in range(len(data) - 1):
+ if int(data[log_index].new_role) == ROLES['engineer']:
+ current_log, next_log = data[log_index], data[log_index + 1]
+ # Если сессия закончилась НЕ в тот же день, что и началась
+ if current_log.change_time.date() != next_log.change_time.date():
+ stat[current_log.change_time.date()] += (timedelta(days=1) - get_timedelta(current_log)).total_seconds()
+ stat[next_log.change_time.date()] += get_timedelta(next_log).total_seconds()
+ # Если проработал несколько дней подряд, то заполнить эти дни по 24 часа
+ for day in daterange(current_log.change_time.date() + timedelta(days=1),next_log.change_time.date()):
+ stat[day] = 24 * 3600
+ # Если сессия закончилась в тот же день, что и началась
+ else:
+ elapsed_time = next_log.change_time - current_log.change_time
+ stat[current_log.change_time.date()] += elapsed_time.total_seconds()
+ return stat
diff --git a/main/forms.py b/main/forms.py
index 7046b35..e98b7e1 100644
--- a/main/forms.py
+++ b/main/forms.py
@@ -71,7 +71,10 @@ class StatisticForm(forms.Form):
label='Электроная почта',
)
interval = forms.CharField( # TODO: Переделать под html страницу
- label='Выбор интервала',
+ label='Интервал работы',
+ )
+ display_format = forms.CharField( # TODO: Переделать под html страницу
+ label='Формат отображения',
)
range_start = forms.DateField( # TODO: Переделать под html страницу
label='Начало диапазона',
diff --git a/main/templates/pages/stat.html b/main/templates/pages/stat.html
index ea5e793..2409e0f 100644
--- a/main/templates/pages/stat.html
+++ b/main/templates/pages/stat.html
@@ -4,7 +4,7 @@
{% block title %}{{ pagename }}{% endblock %}
-{% block heading %}Статистика{% endblock %}
+{% block heading %} Пример страницы статистики(палками не бейти плиз){% endblock %}
{% block extra_css %}
@@ -21,10 +21,17 @@
{% endfor %}
- {% for key,val in stats_logs.items %}
-
{{key}} {{val}}
+ {% for key,val in log_stats.items %}
+
{{key}} | {{val}}
{% endfor %}
+
+
+ {% for error in errors %}
+
{{error}}
+ {% endfor %}
+
+
{% endblock %}
diff --git a/main/views.py b/main/views.py
index 79c14bc..f7a6967 100644
--- a/main/views.py
+++ b/main/views.py
@@ -1,6 +1,6 @@
import logging
import os
-from datetime import timedelta
+from datetime import timedelta, date, datetime
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordResetForm
@@ -21,7 +21,7 @@ from zenpy.lib.api_objects import User as ZenpyUser
from access_controller.settings import EMAIL_HOST_USER, ZENDESK_ROLES
from main.extra_func import check_user_exist, update_profile, get_user_organization, make_engineer, make_light_agent, \
- get_users_list, daterange, get_timedelta
+ get_users_list, last_day_of_month, get_statistic_from_data
from main.forms import AdminPageUsers, CustomRegistrationForm, CustomAuthenticationForm, StatisticForm
from .models import UserProfile, RoleChangeLogs
@@ -230,94 +230,57 @@ class CustomLoginView(LoginView):
def statistic_page(request):
if not request.user.is_superuser:
return redirect('index')
-
context = {
'pagename': 'страница статистики',
+ 'errors': [],
}
-
if request.method == "POST":
form = StatisticForm(request.POST)
-
- if form.is_valid():
- start_date = form.cleaned_data['range_start']
- end_date = form.cleaned_data['range_end']
-
- try:
- data = RoleChangeLogs.objects.filter(
- change_time__range=[start_date, end_date],
- user=User.objects.get(email=form.cleaned_data['email']),
- ).order_by('change_time')
- except User.DoesNotExist:
- context['errors'] = 'Пользователь не найден'
- context['form'] = StatisticForm()
- return render(request, 'pages/stat.html', context)
-
- interval = form.cleaned_data['interval'] # интервал TODO: переделать под html-страницу
- show = form.cleaned_data['display_format'] # формат отображения TODO: переделать под html-страницу
- stat = {}
-
- # Этот кусок кода будет заполнять массив stat, в котором ключ - дата, значение - кол-во секунд
- # Далее будет заполнение контекса в зависимости от выбранного интервала(дни/месяцы) и формата отобржаения(дни/часы)
- # (пока есть только отображение в часах, интервал в днях)
-
- # Обнуление всех дней
- for day in daterange(start_date, end_date + timedelta(days=1)):
- stat[day] = 0
-
- first_log = data[0]
- last_log = data[len(data) - 1]
- # Проеврка крайних случаев
- # Если окажется, что инженер работал ещё до начала диапазона(мы видим, что он был инженером до диапазона)
- if first_log.old_role == 'engineer':
- for day in daterange(start_date, first_log.change_time.date()):
- stat[day] = 24 * 3600
- stat[first_log.change_time.date()] += get_timedelta(first_log.change_time.time()).total_seconds()
-
- # Если окажется, что инженер закончил работать после диапазона(мы видим, что он был инженером и после диапазона)
- if last_log.new_role == 'engineer':
- for day in daterange(last_log.change_time.date() + timedelta(days=1),
- end_date + timedelta(days=1)):
- stat[day] = 24 * 3600
- stat[last_log.change_time.date()] += (timedelta(days=1) - get_timedelta(last_log)).total_seconds()
-
- # Цикл по логам
- for log_index in range(len(data) - 1):
- if data[log_index].new_role == 'engineer':
- current_log, next_log = data[log_index], data[log_index + 1]
-
- # Если сессия закончилась НЕ в тот же день, что и началась
- if current_log.change_time.date() != next_log.change_time.date():
- stat[current_log.change_time.date()] += (
- timedelta(days=1) - get_timedelta(current_log)).total_seconds()
- stat[next_log.change_time.date()] += get_timedelta(next_log).total_seconds()
-
- # Если проработал несколько дней подряд, то заполнить эти дни по 24 часа
- for day in daterange(current_log.change_time.date() + timedelta(days=1),
- next_log.change_time.date()):
- stat[day] = 24 * 3600
-
- # Если сессия закончилась в тот же день, что и началась
- else:
- elapsed_time = next_log.change_time - current_log.change_time
- stat[current_log.change_time.date()] += elapsed_time.total_seconds()
-
- # Переделываем наши значения под формат отображения
- for key, item in stat.items():
- if show == 'hours':
- stat[key] = item / 3600
- elif show == 'days':
- stat[key] = item / 86400
-
- # Переделываем наши значения под формат отображения
- if interval == 'days':
- context['stats_logs'] = stat
- elif interval == 'months':
- pass
+ if not form.is_valid():
+ context['errors'] += form.errors
else:
- context['errors'] = form.errors
+ start_date, end_date, data = form.cleaned_data['range_start'], form.cleaned_data['range_end'], list()
+ if end_date < start_date or end_date > datetime.now().date():
+ context['errors'] += ['Конец диапазона должен быть больше начала диапазона и меньше текущего времени']
+ else:
+ try:
+ data = RoleChangeLogs.objects.filter(
+ change_time__range=[start_date, end_date + timedelta(days=1)],
+ user=User.objects.get(email=form.cleaned_data['email']),
+ ).order_by('change_time')
+ except User.DoesNotExist:
+ context['errors'] = ['Пользователь не найден']
+ stats = get_statistic_from_data(data, start_date, end_date)
+ if stats is None:
+ context['errors'] += ['Не найдено изменений роли в указаном диапазоне']
+ interval = form.cleaned_data['interval'] # интервал работы TODO: переделать под html-страницу
+ show = form.cleaned_data['display_format'] # формат отображения
+ if not (show in ['hours', 'days']): # Работа с форматом отображения
+ context['errors'] += ['Формат отображения должен быть в часах или днях']
+ elif stats:
+ for key, item in stats.items():
+ if show == 'hours':
+ stats[key] = item / 3600
+ elif show == 'days':
+ stats[key] = item / 86400
+
+ if not (interval in ['days', 'months']): # Работа с интервалом работы
+ context['errors'] += ['Интервал работы должен быть в днях или месяцах']
+ elif interval == 'months' and stats: # Переделываем ключи под формат в прототипе(начало_месяца-конец_месяца)
+ new_stats = {}
+ for key, value in stats.items():
+ current_month_start, current_month_end = max(start_date,
+ date(year=key.year, month=key.month, day=1)), min(
+ 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_stats.get(index):
+ new_stats[index] += value
+ else:
+ new_stats[index] = value
+ stats = new_stats
+ context['log_stats'] = stats if not context['errors'] else None
if request.method == 'GET':
form = StatisticForm()
-
context['form'] = form
return render(request, 'pages/stat.html', context)