296 lines
11 KiB
Python
296 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# zoo - versatile objects management
|
|
# Copyright (C) 2016 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import csv
|
|
import io
|
|
import itertools
|
|
import time
|
|
|
|
from django.template.response import TemplateResponse
|
|
from django.views.generic import TemplateView
|
|
from django.shortcuts import redirect, get_object_or_404
|
|
from django.http import Http404, FileResponse, HttpResponseRedirect
|
|
from django.db.transaction import non_atomic_requests, atomic
|
|
from django.db import connection
|
|
from django.conf import settings
|
|
from django.core.cache import cache
|
|
from django.utils.timezone import now, six
|
|
|
|
from django.contrib.auth.decorators import permission_required
|
|
from django.contrib import messages
|
|
|
|
from zoo.zoo_data.models import Entity
|
|
|
|
from . import forms
|
|
from .synchronize_federations import SynchronizeFederationsAction
|
|
from .inactivity import Inactivity
|
|
from . import utils
|
|
|
|
|
|
class Demo(TemplateView):
|
|
template_name = 'zoo_nanterre/demo.html'
|
|
|
|
demo = Demo.as_view()
|
|
|
|
|
|
class Search(TemplateView):
|
|
template_name = 'zoo_nanterre/search.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super(Search, self).get_context_data(**kwargs)
|
|
form = forms.SearchForm(data=self.request.GET or None)
|
|
ctx['form'] = form
|
|
ctx['results'] = list(form.results()) if form.is_valid() else []
|
|
return ctx
|
|
|
|
|
|
class ImportControl(TemplateView):
|
|
template_name = 'zoo_nanterre/import_control.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
ctx = super(ImportControl, self).get_context_data(**kwargs)
|
|
c = connection.cursor()
|
|
c.execute("SELECT count(e.id) from zoo_data_entity as e , zoo_meta_entityschema as s where "
|
|
" e.schema_id = s.id and s.slug = 'individu'")
|
|
ctx['count'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.id) from zoo_data_entity as e , zoo_meta_entityschema as s where "
|
|
" e.schema_id = s.id and s.slug = 'individu' and e.content->>'statut_legal' = 'majeur'")
|
|
ctx['majeurs'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.id) from zoo_data_entity as e , zoo_meta_entityschema as s where "
|
|
" e.schema_id = s.id and s.slug = 'individu' and e.content->>'statut_legal' = 'mineur'")
|
|
ctx['mineurs'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.content->'cles_de_federation'->'technocarte') from "
|
|
"zoo_data_entity as e")
|
|
ctx['federations_technocarte'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.content->'cles_de_federation'->'infor') from "
|
|
"zoo_data_entity as e")
|
|
ctx['federations_infor'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.content->'cles_de_federation'->'implicit') from "
|
|
"zoo_data_entity as e")
|
|
ctx['federations_implicit'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.content->'cles_de_federation'->'saga') from "
|
|
"zoo_data_entity as e")
|
|
ctx['federations_saga'] = c.fetchone()[0]
|
|
c.execute("SELECT count(e.content->'cles_de_federation'->'saga_tiers') from "
|
|
"zoo_data_entity as e")
|
|
ctx['federations_saga_tiers'] = c.fetchone()[0]
|
|
return ctx
|
|
|
|
|
|
search = non_atomic_requests(Search.as_view())
|
|
|
|
import_control = ImportControl.as_view()
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations(request, model_admin, *args, **kwargs):
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
context = dict(
|
|
model_admin.admin_site.each_context(request),
|
|
title='Synchronises les applications',
|
|
jobs=jobs,
|
|
)
|
|
return TemplateResponse(request, "admin/zoo_data/entity/synchronize_federations.html", context)
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_report(request, job_id, model_admin, *args, **kwargs):
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
report = job.action.report
|
|
if not report:
|
|
raise Http404('no report')
|
|
text_report = report
|
|
if six.PY3:
|
|
text_report = io.TextIOWrapper(text_report, encoding='utf-8')
|
|
reader = csv.reader(text_report)
|
|
next(reader)
|
|
actions = [row for row in reader if row[6] != 'KEEP']
|
|
context = dict(
|
|
model_admin.admin_site.each_context(request),
|
|
title=job.created,
|
|
job=job,
|
|
csv=actions,
|
|
csv_url=job.action.download_report_url,
|
|
csv_filesize=report.size,
|
|
)
|
|
return TemplateResponse(request, "admin/zoo_data/entity/synchronize_federations_report.html", context)
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_download_report(request, job_id, model_admin, *args, **kwargs):
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
report = job.action.report
|
|
if not report:
|
|
raise Http404('no report')
|
|
return FileResponse(report, content_type='text/csv')
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_apply_report(request, job_id, model_admin, *args, **kwargs):
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
report = job.action.apply_report
|
|
if not report:
|
|
raise Http404('no report')
|
|
text_report = report
|
|
if six.PY3:
|
|
text_report = io.TextIOWrapper(text_report, encoding='utf-8')
|
|
reader = csv.reader(text_report)
|
|
next(reader)
|
|
actions = [row for row in reader if row[6] != 'KEEP']
|
|
context = dict(
|
|
model_admin.admin_site.each_context(request),
|
|
title=u'Application - %s' % job.created,
|
|
job=job,
|
|
csv=actions,
|
|
csv_url=job.action.download_apply_report_url,
|
|
csv_filesize=report.size,
|
|
)
|
|
return TemplateResponse(request, "admin/zoo_data/entity/synchronize_federations_report.html", context)
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_download_apply_report(request, job_id, model_admin, *args, **kwargs):
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
report = job.action.apply_report
|
|
if not report:
|
|
raise Http404('no report')
|
|
return FileResponse(report, content_type='text/csv')
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_add(request, model_admin, *args, **kwargs):
|
|
if request.method == 'POST':
|
|
form = forms.SynchronizeFederationsForm(request.POST, request.FILES)
|
|
if form.is_valid():
|
|
form.save()
|
|
return redirect('admin:synchronize-federations')
|
|
else:
|
|
form = forms.SynchronizeFederationsForm()
|
|
context = dict(
|
|
model_admin.admin_site.each_context(request),
|
|
form=form,
|
|
)
|
|
return TemplateResponse(request, "admin/zoo_data/entity/synchronize_federations_add.html", context)
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_apply(request, job_id, model_admin, **kwargs):
|
|
if request.method == 'POST':
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
apply_report = job.action.apply_report
|
|
if apply_report:
|
|
raise Http404
|
|
job.action.set_apply(job)
|
|
return redirect('admin:synchronize-federations')
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
def synchronize_federations_delete(request, job_id, model_admin, *args, **kwargs):
|
|
if request.method == 'POST':
|
|
jobs = SynchronizeFederationsAction.get_jobs()
|
|
job = get_object_or_404(jobs, id=job_id)
|
|
job.action.delete()
|
|
job.delete()
|
|
return redirect('admin:synchronize-federations')
|
|
|
|
|
|
def fiches_inactives():
|
|
inactivity = Inactivity(
|
|
child_delay=getattr(settings, 'ZOO_NANTERRE_INACTIVITY_CHILD_DELAY', 365), # default 12 months
|
|
adult_delay=getattr(settings, 'ZOO_NANTERRE_INACTIVITY_ADULT_DELAY', 182), # default 6 months
|
|
)
|
|
fiches = []
|
|
for child in itertools.chain(inactivity.deletable_children, inactivity.deletable_adults):
|
|
utils.PersonSearch.add_age(child)
|
|
fiches.append({
|
|
'id': child.id,
|
|
'prenoms': child.content['prenoms'],
|
|
'nom_de_naissance': child.content['nom_de_naissance'],
|
|
'nom_d_usage': child.content['nom_d_usage'],
|
|
'date_de_naissance': child.content['date_de_naissance'],
|
|
'statut_legal': child.content['statut_legal'],
|
|
'age': child.age_label,
|
|
})
|
|
fiches.sort(key=lambda f: f['id'])
|
|
return fiches
|
|
|
|
|
|
@permission_required('zoo_data.action1_entity')
|
|
@atomic
|
|
def inactive_index(request, model_admin, *args, **kwargs):
|
|
try:
|
|
timestamp, fiches = cache.get('fiches-inactives')
|
|
|
|
if 'recompute' in request.GET:
|
|
cache.delete('fiches-inactives')
|
|
return HttpResponseRedirect(request.path)
|
|
|
|
# delete operation
|
|
if 'delete' in request.GET and request.method == 'POST':
|
|
new_timestamp = now()
|
|
new_fiches = fiches_inactives()
|
|
if fiches != new_fiches:
|
|
messages.warning(request, u'Les fiches à supprimer ont changées.')
|
|
cache.set('fiches-inactives', (new_timestamp, new_fiches), 365 * 24 * 3600)
|
|
else:
|
|
Entity.objects.filter(id__in=[fiche['id'] for fiche in fiches]).delete()
|
|
messages.info(request, u'%d fiches ont été supprimées.' % len(fiches))
|
|
cache.delete('fiches-inactives')
|
|
return HttpResponseRedirect(request.path)
|
|
duration = None
|
|
queries = None
|
|
except (TypeError, ValueError):
|
|
try:
|
|
connection.force_debug_cursor = True
|
|
start = time.time()
|
|
fiches = fiches_inactives()
|
|
queries = len(connection.queries_log)
|
|
duration = time.time() - start
|
|
timestamp = now()
|
|
cache.set('fiches-inactives', (timestamp, fiches), 365 * 24 * 3600)
|
|
finally:
|
|
connection.force_debug_cursor = False
|
|
|
|
# download csv export
|
|
if 'csv' in request.GET:
|
|
header = ['id', 'prenoms', 'nom_d_usage', 'nom_de_naissance',
|
|
'date_de_naissance', 'statut_legal', 'age']
|
|
|
|
def rows():
|
|
yield header
|
|
for fiche in fiches:
|
|
yield [fiche[key] for key in header]
|
|
return utils.csv_export_response(rows(), 'fiches-inactives-%s.csv' % timestamp)
|
|
|
|
context = dict(
|
|
model_admin.admin_site.each_context(request),
|
|
title='Fiches inactives à supprimer',
|
|
fiches=fiches,
|
|
timestamp=timestamp,
|
|
duration=duration,
|
|
queries=queries,
|
|
child_delay=getattr(settings, 'ZOO_NANTERRE_INACTIVITY_CHILD_DELAY', 365),
|
|
adult_delay=getattr(settings, 'ZOO_NANTERRE_INACTIVITY_ADULT_DELAY', 365),
|
|
)
|
|
return TemplateResponse(request, "admin/zoo_data/entity/inactive_index.html", context)
|