summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation.html19
-rw-r--r--archaeological_operations/urls.py4
-rw-r--r--archaeological_operations/views.py37
-rw-r--r--archaeological_warehouse/models.py6
-rw-r--r--archaeological_warehouse/templates/ishtar/sheet_container.html22
-rw-r--r--archaeological_warehouse/templates/ishtar/sheet_warehouse.html19
-rw-r--r--archaeological_warehouse/urls.py8
-rw-r--r--archaeological_warehouse/views.py25
-rw-r--r--ishtar_common/models.py31
9 files changed, 147 insertions, 24 deletions
diff --git a/archaeological_operations/templates/ishtar/sheet_operation.html b/archaeological_operations/templates/ishtar/sheet_operation.html
index ef5de7f59..868040666 100644
--- a/archaeological_operations/templates/ishtar/sheet_operation.html
+++ b/archaeological_operations/templates/ishtar/sheet_operation.html
@@ -408,7 +408,24 @@
<div class="tab-pane fade" id="{{window_id}}-statistics"
role="tabpanel" aria-labelledby="{{window_id}}-statistics-tab">
<h3>{% trans "Statistics" %}</h3>
- <small class="centered"><em>{% trans "These numbers are updated hourly" %}</em></small>
+
+ <div class="row mt-2 mb-2">
+ <div class="col">
+ <div class="btn-group btn-group-sm" role="group"
+ aria-label="{% trans 'Export' %}">
+ <a class="btn btn-success"
+ onclick="long_wait();return true;"
+ href="{% url 'generate-stats-operation' item.pk %}">
+
+ {% trans "Regenerate statistics" %}
+ </a>
+ </div>
+ {% with item.last_stats_update as last_stats_update%}
+ {% if last_stats_update %}<small class="ml-2">
+ <em>{% trans "Last update:" %} {{last_stats_update}}</em>
+ </small>{% endif %}{% endwith %}
+ </div>
+ </div>
<h4>{% trans "Administrative acts" %}</h4>
<div class='row'>
diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py
index 77791058a..72e06641d 100644
--- a/archaeological_operations/urls.py
+++ b/archaeological_operations/urls.py
@@ -212,4 +212,8 @@ urlpatterns = [
'change_own_archaeologicalsite'])(
views.QAArchaeologicalSiteForm.as_view()),
name='site-qa-bulk-update-confirm', kwargs={"confirm": True}),
+
+ url(r'generate-stats-operation/(?P<pk>.+)/',
+ views.GenerateStatsOperation.as_view(),
+ name='generate-stats-operation'),
]
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index ecacdb560..897302828 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -25,6 +25,7 @@ from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render, redirect
+from django.views.generic import RedirectView
from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy
from archaeological_operations import models
@@ -36,7 +37,8 @@ from ishtar_common.models import get_current_profile, IshtarSiteProfile, \
DocumentTemplate
from ishtar_common.utils import put_session_message, check_rights_condition
from ishtar_common.views import gen_generate_doc, QAItemEditForm, \
- QABaseLockView, wizard_is_available, QAItemForm
+ QABaseLockView, wizard_is_available, QAItemForm, IshtarMixin, \
+ LoginRequiredMixin
from ishtar_common.views_item import get_item, show_item, revert_item, \
new_qa_item
from ishtar_common.wizards import SearchWizard
@@ -644,3 +646,36 @@ class QAArchaeologicalSiteDuplicateFormView(QAItemForm):
class QAArchaeologicalSiteForm(QAItemEditForm):
model = models.ArchaeologicalSite
form_class = forms.QAArchaeologicalSiteFormMulti
+
+
+class GenerateStatsOperation(IshtarMixin, LoginRequiredMixin, RedirectView):
+ model = models.Operation
+
+ def get_redirect_url(self, *args, **kwargs):
+ return reverse('display-item',
+ args=[self.model.SLUG, self.item.pk]) + "#statistics"
+
+ def get(self, request, *args, **kwargs):
+ self.item = self.model.objects.get(pk=kwargs['pk'])
+ self.item._get_or_set_stats('_nb_acts', update=True)
+ self.item._get_or_set_stats('_nb_indexed_acts', update=True)
+ self.item._get_or_set_stats('_nb_context_records', update=True)
+ self.item._get_or_set_stats('_nb_context_records_by_type', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_nb_context_records_by_periods',
+ update=True, expected_type=list)
+ self.item._get_or_set_stats('_nb_finds', update=True)
+ self.item._get_or_set_stats('_nb_finds_by_material_type', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_nb_finds_by_types', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_nb_finds_by_periods', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_nb_documents', update=True)
+ self.item._get_or_set_stats('_nb_documents_by_types', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_nb_stats_finds_by_ue', update=True)
+
+ return super(GenerateStatsOperation, self).get(request, *args, **kwargs)
+
+
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index ffc491ddc..f89092dba 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -118,7 +118,8 @@ class DivisionContainer(DashboardFormItem):
@property
def number_of_finds_by_place(self, update=False):
- return self._get_or_set_stats('_number_of_finds_by_place', update)
+ return self._get_or_set_stats('_number_of_finds_by_place', update,
+ expected_type=list)
def _number_of_containers_by_place(self):
return self._number_of_items_by_place(
@@ -126,7 +127,8 @@ class DivisionContainer(DashboardFormItem):
@property
def number_of_containers_by_place(self, update=False):
- return self._get_or_set_stats('_number_of_containers_by_place', update)
+ return self._get_or_set_stats('_number_of_containers_by_place', update,
+ expected_type=list)
def _get_divisions(self, current_path, remaining_division, depth=0):
if not remaining_division:
diff --git a/archaeological_warehouse/templates/ishtar/sheet_container.html b/archaeological_warehouse/templates/ishtar/sheet_container.html
index 336684bc8..7ca39645d 100644
--- a/archaeological_warehouse/templates/ishtar/sheet_container.html
+++ b/archaeological_warehouse/templates/ishtar/sheet_container.html
@@ -154,7 +154,23 @@
role="tabpanel" aria-labelledby="{{window_id}}-stats-tab">
<h3>{% trans "Statistics" %}</h3>
- <small class="centered"><em>{% trans "These numbers are updated hourly" %}</em></small>
+ <div class="row mt-2 mb-2">
+ <div class="col">
+ <div class="btn-group btn-group-sm" role="group"
+ aria-label="{% trans 'Export' %}">
+ <a class="btn btn-success"
+ onclick="long_wait();return true;"
+ href="{% url 'generate-stats-container' item.pk %}">
+
+ {% trans "Regenerate statistics" %}
+ </a>
+ </div>
+ {% with item.last_stats_update as last_stats_update%}
+ {% if last_stats_update %}<small class="ml-2">
+ <em>{% trans "Last update:" %} {{last_stats_update}}</em>
+ </small>{% endif %}{% endwith %}
+ </div>
+ </div>
{% if not item.number_containers and not item.number_divisions %}
<div class="alert alert-info">
@@ -188,10 +204,8 @@
{% endif %}
{% endfor %}
- <h4>{% trans "Containers" %}</h4>
-
{% if item.number_of_containers_by_place %}
- <h4>{% trans "Containers by location in the warehouse" %}</h4>
+ <h4>{% trans "Containers by location" %}</h4>
{% for items in item.number_of_containers_by_place %}
{% if items %}
<table class='table table-striped datatables'
diff --git a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
index e6717f230..b4786de5b 100644
--- a/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
+++ b/archaeological_warehouse/templates/ishtar/sheet_warehouse.html
@@ -136,7 +136,24 @@
<div class="tab-pane fade" id="{{window_id}}-stats"
role="tabpanel" aria-labelledby="{{window_id}}-stats-tab">
<h3>{% trans "Statistics" %}</h3>
- <small class="centered"><em>{% trans "These numbers are updated hourly" %}</em></small>
+
+ <div class="row mt-2 mb-2">
+ <div class="col">
+ <div class="btn-group btn-group-sm" role="group"
+ aria-label="{% trans 'Export' %}">
+ <a class="btn btn-success"
+ onclick="long_wait();return true;"
+ href="{% url 'generate-stats-warehouse' item.pk %}">
+
+ {% trans "Regenerate statistics" %}
+ </a>
+ </div>
+ {% with item.last_stats_update as last_stats_update%}
+ {% if last_stats_update %}<small class="ml-2">
+ <em>{% trans "Last update:" %} {{last_stats_update}}</em>
+ </small>{% endif %}{% endwith %}
+ </div>
+ </div>
{% if not item.number_containers and not item.number_divisions %}
<div class="alert alert-info">
diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py
index 2f43d74a6..46d812def 100644
--- a/archaeological_warehouse/urls.py
+++ b/archaeological_warehouse/urls.py
@@ -128,4 +128,12 @@ urlpatterns = [
url(r'container-manual-merge-items/(?P<pks>[0-9_]+?)/$',
views.ContainerManualMergeItems.as_view(),
name='container_manual_merge_items'),
+
+ url(r'generate-stats-container/(?P<pk>.+)/',
+ views.GenerateStatsContainer.as_view(),
+ name='generate-stats-container'),
+
+ url(r'generate-stats-warehouse/(?P<pk>.+)/',
+ views.GenerateStatsWarehouse.as_view(),
+ name='generate-stats-warehouse'),
]
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py
index 34def58cf..de0c64d19 100644
--- a/archaeological_warehouse/views.py
+++ b/archaeological_warehouse/views.py
@@ -21,6 +21,7 @@ import json
from django.core.urlresolvers import reverse
from django.db.models import Q
+from django.views.generic import RedirectView
from django.views.generic.edit import FormView
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import redirect
@@ -313,3 +314,27 @@ class QAContainerForm(QAItemEditForm):
# item list is necessary to verify uniqueness rules
kwargs['items'] = self.items
return kwargs
+
+
+class GenerateStats(IshtarMixin, LoginRequiredMixin, RedirectView):
+ model = None
+
+ def get_redirect_url(self, *args, **kwargs):
+ return reverse('display-item',
+ args=[self.model.SLUG, self.item.pk]) + "#stats"
+
+ def get(self, request, *args, **kwargs):
+ self.item = self.model.objects.get(pk=kwargs['pk'])
+ self.item._get_or_set_stats('_number_of_finds_by_place', update=True,
+ expected_type=list)
+ self.item._get_or_set_stats('_number_of_containers_by_place',
+ update=True, expected_type=list)
+ return super(GenerateStats, self).get(request, *args, **kwargs)
+
+
+class GenerateStatsContainer(GenerateStats):
+ model = models.Container
+
+
+class GenerateStatsWarehouse(GenerateStats):
+ model = models.Warehouse
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 2d3320e2e..6eea042ce 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -3403,33 +3403,34 @@ class DashboardFormItem(object):
Provide methods to manage statistics
"""
- def _get_or_set_stats(self, funcname, update,
- timeout=settings.CACHE_TIMEOUT,
+ def last_stats_update(self):
+ model_name = self._meta.app_label + "." + self._meta.model_name
+ q = StatsCache.objects.filter(
+ model=model_name, model_pk=self.pk).order_by("-updated")
+ if not q.count():
+ return
+ return q.all()[0].updated
+
+ def _get_or_set_stats(self, funcname, update=False,
expected_type=None):
- values = {}
- from_cache = False
model_name = self._meta.app_label + "." + self._meta.model_name
sc, __ = StatsCache.objects.get_or_create(
model=model_name, model_pk=self.pk
)
- now = datetime.datetime.now()
- if not settings.DEBUG and (
- not update and sc.values and funcname in sc.values and (
- sc.updated + datetime.timedelta(seconds=timeout)) > now):
+ if not update:
values = sc.values
- from_cache = True
- if funcname not in values:
+ if funcname not in values:
+ if expected_type is not None:
+ return expected_type()
+ return 0
+ else:
values = update_stats(sc, self, funcname)
if funcname in values:
values = values[funcname]
else:
values = 0
if expected_type is not None and not isinstance(values, expected_type):
- if from_cache:
- return self._get_or_set_stats(funcname, True,
- expected_type=expected_type)
- else:
- return expected_type()
+ return expected_type()
return values
@classmethod