Merge pull request 'ruzne exporty resitelu - zatím určitě ne merge xd spíš potřebuji zpětnou vazbu...' (!89) from export_resitelskych_dat into master
Reviewed-on: #89
This commit is contained in:
commit
ff7d36a965
5 changed files with 236 additions and 1 deletions
88
personalni/templates/personalni/profil/export_lidi.html
Normal file
88
personalni/templates/personalni/profil/export_lidi.html
Normal file
|
@ -0,0 +1,88 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2><strong>Export lidí</strong></h2>
|
||||
|
||||
<select name="select-one" id="select-one">
|
||||
<option value="0">---</option>
|
||||
<option value="1">Řešitelé čísla</option>
|
||||
<option value="2">Řešitelé ročníku</option>
|
||||
<option value="3">Všichni řešitelé, kteří ještě neodmaturovali</option>
|
||||
<option value="4">Organizátoři soustředění</option>
|
||||
</select>
|
||||
|
||||
<select name="select-two" id="select-two">
|
||||
<!-- will be filled with ajax -->
|
||||
</select>
|
||||
|
||||
<button id="download-button">Stáhnout</button>
|
||||
|
||||
<script defer>
|
||||
const select_one = document.getElementById("select-one")
|
||||
const select_two = document.getElementById("select-two")
|
||||
const download_button = document.getElementById("download-button")
|
||||
|
||||
download_button.style.display = 'none'
|
||||
select_two.style.display = 'none'
|
||||
|
||||
const fetch_dict_string = '{{ typy_exportu|safe }}'
|
||||
const fetch_dict = JSON.parse(fetch_dict_string)
|
||||
|
||||
|
||||
select_one.addEventListener('change', (e) => {
|
||||
value = e.target.value
|
||||
select_two.style.display = 'none'
|
||||
select_two.innerHTML = ''
|
||||
// puvodni stav
|
||||
if (value == 0) {
|
||||
download_button.style.display = 'none'
|
||||
select_two.style.display = 'none'
|
||||
return
|
||||
}
|
||||
// v tomto pripade muzeme rovnou stahnout
|
||||
if (!(value in fetch_dict)) {
|
||||
download_button.style.display = 'block'
|
||||
select_two.style.display = 'none'
|
||||
return
|
||||
}
|
||||
download_button.style.display = 'none'
|
||||
fetch("/profil/exporty_lidi/get/" + value)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const option = document.createElement('option')
|
||||
option.value = 0
|
||||
option.text = '---'
|
||||
select_two.appendChild(option)
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
const option = document.createElement('option')
|
||||
option.value = value["id"]
|
||||
option.text = value["display"]
|
||||
select_two.appendChild(option)
|
||||
}
|
||||
select_two.style.display = 'block'
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
select_two.addEventListener('change', (e) => {
|
||||
value = e.target.value
|
||||
if (value == 0) {
|
||||
download_button.style.display = 'none'
|
||||
return
|
||||
}
|
||||
download_button.style.display = 'block'
|
||||
})
|
||||
|
||||
download_button.addEventListener('click', (e) => {
|
||||
if (select_two.innerHTML == '') {
|
||||
window.location.href = "/profil/exporty_lidi/get_csv_only_one_step/" + select_one.value
|
||||
} else {
|
||||
window.location.href = "/profil/exporty_lidi/get_csv/" + select_one.value + "/" + select_two.value
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -107,6 +107,13 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
<h2><strong>Exporty dat lidí v semináří</strong></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="{% url 'exporty_lidi' %}">dostupné exporty</a></li>
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
<p>Nemůžeš najít, co hledáš? Může to být v <a href="{% url 'admin:index' %}">administračním rozhraní webu</a>.</p>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -38,6 +38,28 @@ urlpatterns = [
|
|||
'org/propagace/jak-se-dozvedeli/',
|
||||
org_required(views.JakSeDozvedeliView.as_view()),
|
||||
name='jak_se_dozvedeli'
|
||||
),
|
||||
|
||||
# export dat o řešitelích
|
||||
path(
|
||||
'profil/exporty_lidi',
|
||||
org_required(views.ExportLidiView.as_view()),
|
||||
name='exporty_lidi',
|
||||
),
|
||||
path(
|
||||
'profil/exporty_lidi/get/<int:type>',
|
||||
org_required(views.get_export_options),
|
||||
name='exporty_lidi_options',
|
||||
),
|
||||
path(
|
||||
'profil/exporty_lidi/get_csv_only_one_step/<int:type>',
|
||||
org_required(views.download_export_csv_only_first_step),
|
||||
name='exporty_lidi_data',
|
||||
),
|
||||
path(
|
||||
'profil/exporty_lidi/get_csv/<int:type>/<int:id>',
|
||||
org_required(views.download_export_csv),
|
||||
name='exporty_lidi_download',
|
||||
)
|
||||
|
||||
]
|
||||
|
|
|
@ -20,13 +20,16 @@ from django.utils import timezone
|
|||
import personalni.models as m
|
||||
from soustredeni.models import Soustredeni
|
||||
from odevzdavatko.models import Hodnoceni
|
||||
from tvorba.models import Clanek, Uloha, Tema
|
||||
from tvorba.models import Clanek, Uloha, Tema, Cislo, Rocnik
|
||||
import tvorba.utils as tvorba_utils
|
||||
from various.models import Nastaveni
|
||||
from .forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm
|
||||
|
||||
from datetime import date
|
||||
import logging
|
||||
import csv
|
||||
from enum import Enum
|
||||
import json
|
||||
|
||||
from various.views.pomocne import formularOKView
|
||||
from various.autentizace.views import LoginView
|
||||
|
@ -141,6 +144,54 @@ class OrgoRozcestnikView(TemplateView):
|
|||
#content_type = 'text/plain; charset=UTF8'
|
||||
#XXX
|
||||
|
||||
class PrvniTypExportu(Enum):
|
||||
CISLA = 1
|
||||
ROCNIKU = 2
|
||||
SOUSTREDENI = 4
|
||||
|
||||
class ExportLidiView(TemplateView):
|
||||
template_name = 'personalni/profil/export_lidi.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['typy_exportu'] = json.dumps({member.value: member.name.lower().capitalize() for member in PrvniTypExportu})
|
||||
return context
|
||||
|
||||
|
||||
def get_export_options(request, type):
|
||||
if type == PrvniTypExportu.CISLA.value:
|
||||
data = [{"id": c.id, "display": str(c)} for c in Cislo.objects.all()]
|
||||
if type == PrvniTypExportu.ROCNIKU.value:
|
||||
data = [{"id": r.id, "display": str(r)} for r in Rocnik.objects.all()]
|
||||
if type == PrvniTypExportu.SOUSTREDENI.value:
|
||||
data = [{"id": s.id, "display": str(s)} for s in Soustredeni.objects.all()]
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
|
||||
def download_export_csv_only_first_step(request, type):
|
||||
if type == 3:
|
||||
response = dataResiteluCsvResponse(tvorba_utils.resitele_co_neodmaturovali())
|
||||
response['Content-Disposition'] = 'attachment; filename="resitele_co_neodmaturovali.csv"'
|
||||
return response
|
||||
|
||||
def download_export_csv(request, type, id):
|
||||
if type == PrvniTypExportu.CISLA.value:
|
||||
response = dataResiteluCsvResponse(tvorba_utils.resi_cislo(Cislo.objects.get(id=id)))
|
||||
name = str(Cislo.objects.get(id=id)).replace(" ", "_") + "_resitele_cisla.csv"
|
||||
response['Content-Disposition'] = 'attachment; filename="' + name + '"'
|
||||
return response
|
||||
if type == PrvniTypExportu.ROCNIKU.value:
|
||||
response = dataResiteluCsvResponse(tvorba_utils.resi_v_rocniku(Rocnik.objects.get(id=id)))
|
||||
name = str(Rocnik.objects.get(id=id)).replace(" ", "_") + "_resitele_rocniku.csv"
|
||||
response['Content-Disposition'] = 'attachment; filename="' + name + '"'
|
||||
return response
|
||||
if type == PrvniTypExportu.SOUSTREDENI.value:
|
||||
soustredeni = Soustredeni.objects.get(id=id)
|
||||
organizatori = soustredeni.organizatori.all()
|
||||
organizatoriOsoby = Osoba.objects.filter(org__in=organizatori)
|
||||
response = dataOsobCsvResponse(organizatoriOsoby, columns=("jmeno", "prijmeni", "email", "telefon",))
|
||||
name = str(soustredeni).replace(" ", "_") + "_organizatori_soustredeni.csv"
|
||||
response['Content-Disposition'] = 'attachment; filename="' + name + '"'
|
||||
return response
|
||||
|
||||
class ResitelView(LoginRequiredMixin,generic.DetailView):
|
||||
model = m.Resitel
|
||||
|
@ -470,3 +521,46 @@ def dataResiteluCsvResponse(queryset, columns=None, with_header=True):
|
|||
writer.writerows(queryset_list)
|
||||
|
||||
return response
|
||||
|
||||
def dataOsobCsvResponse(queryset, columns=None, with_header=True):
|
||||
"""Pomocná funkce pro vracení dat osob jako CSV. Musí dostat správný QuerySet, který dává Ososby"""
|
||||
|
||||
default_columns = (
|
||||
'id',
|
||||
'jmeno',
|
||||
'prijmeni',
|
||||
'prezdivka',
|
||||
'email',
|
||||
'telefon',
|
||||
'datum_narozeni',
|
||||
'osloveni',
|
||||
'ulice',
|
||||
'mesto',
|
||||
'psc',
|
||||
'stat',
|
||||
'jak_se_dozvedeli',
|
||||
'poznamka',
|
||||
'datum_registrace',
|
||||
'datum_souhlasu_udaje',
|
||||
'datum_souhlasu_zasilani',
|
||||
)
|
||||
|
||||
if columns is None: columns = default_columns
|
||||
|
||||
def get_field_name(column_name):
|
||||
return column_name
|
||||
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
writer = csv.writer(response)
|
||||
|
||||
# První řádek je záhlaví
|
||||
if with_header:
|
||||
writer.writerow(map(get_field_name, columns))
|
||||
|
||||
# Data:
|
||||
queryset_list = queryset.values_list(*columns)
|
||||
writer.writerows(queryset_list)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,30 @@ def resi_v_rocniku(rocnik, cislo=None):
|
|||
reseni__hodnoceni__deadline_body__cislo__poradi__lte=cislo.poradi
|
||||
).distinct()
|
||||
|
||||
def resi_cislo(cislo):
|
||||
""" Vrátí seznam řešitelů, co vyřešili nějaký problém v daném čísle.
|
||||
Parametry:
|
||||
cislo (typu Cislo) číslo, ve kterém chci řešitele, co něco odevzdali
|
||||
Výstup:
|
||||
QuerySet objektů typu Resitel
|
||||
"""
|
||||
|
||||
return personalni.models.Resitel.objects.filter(
|
||||
reseni__hodnoceni__deadline_body__cislo=cislo
|
||||
).distinct()
|
||||
|
||||
def resitele_co_neodmaturovali():
|
||||
""" Vrátí seznam řešitelů, co ještě neodmaturovali.
|
||||
Pokud ještě není srpen, tak zahrnuje i ty, kteří odmaturovali letos.
|
||||
|
||||
Výstup:
|
||||
QuerySet objektů typu Resitel """
|
||||
from datetime import datetime
|
||||
current_year = datetime.now().year
|
||||
if datetime.now().month < 8:
|
||||
current_year -= 1
|
||||
return personalni.models.Resitel.objects.filter(rok_maturity__gte=current_year)
|
||||
|
||||
|
||||
def aktivniResitele(cislo, pouze_letosni=False):
|
||||
""" Vrací QuerySet aktivních řešitelů, což jsou ti, co ještě neodmaturovali
|
||||
|
|
Loading…
Reference in a new issue