diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py index 39e9dcbafb..623a557f2b 100644 --- a/mayan/apps/documents/apps.py +++ b/mayan/apps/documents/apps.py @@ -72,7 +72,7 @@ from .permissions import ( permission_document_view ) from .settings import setting_thumbnail_size -from .statistics import DocumentStatistics, DocumentUsageStatistics +from .statistics import document_page_count_per_month from .widgets import document_thumbnail @@ -351,12 +351,9 @@ class DocumentsApp(MayanAppConfig): namespace = StatisticNamespace(name='documents', label=_('Documents')) namespace.add_statistic( - DocumentStatistics( - name='document_stats', label=_('Document tendencies') - ) - ) - namespace.add_statistic(DocumentUsageStatistics( - name='document_usage', label=_('Document usage')) + slug='document-page-count-per-month', + label=_('Document page count per month'), + func=document_page_count_per_month ) post_initial_setup.connect( diff --git a/mayan/apps/documents/statistics.py b/mayan/apps/documents/statistics.py index 63f0bfba0e..4ca0a641ea 100644 --- a/mayan/apps/documents/statistics.py +++ b/mayan/apps/documents/statistics.py @@ -40,15 +40,23 @@ def storage_count(path='.'): return total_count, total_size -class DocumentStatistics(Statistic): - def get_results(self): - results = [] +def document_page_count_per_month(): + return ( + ( + {'August, 2015': 1244}, + {'September, 2015': 3123}, + ), + ) - results.extend( - [ - _('Document types: %d') % DocumentType.objects.count(), - ] - ) + + #def get_results(self): + # return ( + ## ( + # {_('Document types'): DocumentType.objects.count()}, + # ), + # ) + +""" document_stats = DocumentVersion.objects.annotate( page_count=Count('pages') ).aggregate(Min('page_count'), Max('page_count'), Avg('page_count')) @@ -67,7 +75,7 @@ class DocumentStatistics(Statistic): ) return results - +""" class DocumentUsageStatistics(Statistic): def get_results(self): diff --git a/mayan/apps/statistics/admin.py b/mayan/apps/statistics/admin.py new file mode 100644 index 0000000000..054a35ce00 --- /dev/null +++ b/mayan/apps/statistics/admin.py @@ -0,0 +1,12 @@ +from __future__ import unicode_literals + +from django.contrib import admin + +from .models import StatisticResult + + +@admin.register(StatisticResult) +class StatisticResultAdmin(admin.ModelAdmin): + list_display = ( + 'slug', 'datetime', 'serialize_data' + ) diff --git a/mayan/apps/statistics/apps.py b/mayan/apps/statistics/apps.py index ac4f37595d..5d051fac0e 100644 --- a/mayan/apps/statistics/apps.py +++ b/mayan/apps/statistics/apps.py @@ -1,7 +1,12 @@ from __future__ import unicode_literals +from datetime import timedelta + +from kombu import Exchange, Queue + from django.utils.translation import ugettext_lazy as _ +from mayan.celery import app from common import MayanAppConfig, menu_object, menu_secondary, menu_tools from .classes import Statistic, StatisticNamespace @@ -9,6 +14,8 @@ from .links import ( link_execute, link_namespace_details, link_namespace_list, link_statistics ) +from .literals import STATISTICS_REFRESH_INTERVAL +from .tasks import task_check_statistics # NOQA - Force registration of task class StatisticsApp(MayanAppConfig): @@ -18,6 +25,32 @@ class StatisticsApp(MayanAppConfig): def ready(self): super(StatisticsApp, self).ready() + app.conf.CELERYBEAT_SCHEDULE.update( + { + 'statistics.task_check_statistics': { + 'task': 'statistics.tasks.task_check_statistics', + 'schedule': timedelta(seconds=STATISTICS_REFRESH_INTERVAL), + }, + } + ) + + app.conf.CELERY_QUEUES.extend( + ( + Queue( + 'statistics', Exchange('statistics'), + routing_key='statistics', delivery_mode=1 + ), + ) + ) + + app.conf.CELERY_ROUTES.update( + { + 'statistics.tasks.task_check_statistics': { + 'queue': 'statistics' + }, + } + ) + menu_object.bind_links(links=(link_execute,), sources=(Statistic,)) menu_object.bind_links( links=(link_namespace_details,), sources=(StatisticNamespace,) diff --git a/mayan/apps/statistics/classes.py b/mayan/apps/statistics/classes.py index 329f6843fd..cfd2a3b5e7 100644 --- a/mayan/apps/statistics/classes.py +++ b/mayan/apps/statistics/classes.py @@ -1,3 +1,8 @@ +from __future__ import unicode_literals + +from .models import StatisticResult + + class StatisticNamespace(object): _registry = {} @@ -18,9 +23,10 @@ class StatisticNamespace(object): def __unicode__(self): return unicode(self.label) - def add_statistic(self, statistic): - self._statistics.append(statistic) + def add_statistic(self, *args, **kwargs): + statistic = Statistic(*args, **kwargs) statistic.namespace = self + self._statistics.append(statistic) @property def id(self): @@ -39,20 +45,33 @@ class Statistic(object): return cls._registry.values() @classmethod - def get(cls, name): - return cls._registry[name] + def get(cls, slug): + return cls._registry[slug] - def __init__(self, name, label): - self.name = name + def __init__(self, slug, label, func): + self.slug = slug self.label = label - self.__class__._registry[name] = self + self.func = func + self.__class__._registry[slug] = self def __unicode__(self): return unicode(self.label) - def get_results(self, *args, **kwargs): - return NotImplementedError + def execute(self): + self.store_results(results=self.func()) @property def id(self): - return self.name + return self.slug + + def store_results(self, results): + StatisticResult.objects.filter(slug=self.slug).delete() + + statistic_result = StatisticResult.objects.create(slug=self.slug) + statistic_result.store_data(data=results) + + def get_results(self): + try: + return StatisticResult.objects.get(slug=self.slug).get_data() + except StatisticResultDoesNotExist: + return ((),) diff --git a/mayan/apps/statistics/literals.py b/mayan/apps/statistics/literals.py new file mode 100644 index 0000000000..1e19e26d4d --- /dev/null +++ b/mayan/apps/statistics/literals.py @@ -0,0 +1,3 @@ +from __future__ import unicode_literals + +STATISTICS_REFRESH_INTERVAL = 60 * 60 # Every hour diff --git a/mayan/apps/statistics/migrations/0001_initial.py b/mayan/apps/statistics/migrations/0001_initial.py new file mode 100644 index 0000000000..5c3d726f81 --- /dev/null +++ b/mayan/apps/statistics/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='StatisticResult', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('slug', models.SlugField(verbose_name='Slug')), + ('datetime', models.DateTimeField(auto_now=True, verbose_name='Date time')), + ('serialize_data', models.TextField(verbose_name='Data', blank=True)), + ], + options={ + 'verbose_name': 'Statistics result', + 'verbose_name_plural': 'Statistics results', + }, + bases=(models.Model,), + ), + ] diff --git a/mayan/apps/statistics/migrations/__init__.py b/mayan/apps/statistics/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayan/apps/statistics/models.py b/mayan/apps/statistics/models.py new file mode 100644 index 0000000000..d2adf6516e --- /dev/null +++ b/mayan/apps/statistics/models.py @@ -0,0 +1,30 @@ +from __future__ import unicode_literals + +import json + +from django.db import models +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext_lazy as _ + + +@python_2_unicode_compatible +class StatisticResult(models.Model): + slug = models.SlugField(verbose_name=_('Slug')) + datetime = models.DateTimeField( + auto_now=True, verbose_name=_('Date time') + ) + serialize_data = models.TextField(blank=True, verbose_name=_('Data')) + + def get_data(self): + return json.loads(self.serialize_data) + + def store_data(self, data): + self.serialize_data = json.dumps(data) + self.save() + + def __str__(self): + return self.slug + + class Meta: + verbose_name = _('Statistics result') + verbose_name_plural = _('Statistics results') diff --git a/mayan/apps/statistics/tasks.py b/mayan/apps/statistics/tasks.py new file mode 100644 index 0000000000..7013bcf45a --- /dev/null +++ b/mayan/apps/statistics/tasks.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +import logging + +from mayan.celery import app + +from .classes import StatisticNamespace + +logger = logging.getLogger(__name__) + + +@app.task(ignore_result=True) +def task_check_statistics(): + logger.info('Executing') + + for namespace in StatisticNamespace.get_all(): + for statistic in namespace.statistics: + statistic.execute() + + logger.info('Finshed') diff --git a/mayan/apps/statistics/urls.py b/mayan/apps/statistics/urls.py index a952799240..c535da3652 100644 --- a/mayan/apps/statistics/urls.py +++ b/mayan/apps/statistics/urls.py @@ -12,7 +12,7 @@ urlpatterns = patterns( NamespaceDetailView.as_view(), name='namespace_details' ), url( - r'^(?P\w+)/execute/$', StatisticExecute.as_view(), + r'^(?P[\w,-]+)/view/$', StatisticExecute.as_view(), name='statistic_execute' ), )