Commit 1a806882 authored by Aaron Iemma's avatar Aaron Iemma 🎨
Browse files

added reports

parent 583e3f36
language: python
python:
- "3.4"
install:
- pip install -r requirements.txt
- cd ..
- django-admin.py startproject --template=./edge --extension=py,md,html,env my_proj
- cd my_proj/src
- cp my_proj/settings/local.sample.env my_proj/settings/local.env
- python manage.py migrate
script:
- python manage.py test profiles
Save the Prince!
==========================
Save the Prince! è un progetto della community [WWF YOUng Italia][0] volto a promuovere e coordinare gli sforzi dei volontari impegnati nei salvataggi degli anfibi dagli investimenti stradali: durante le migrazioni primaverili verso i luoghi di riproduzione, tale classe di sensibilissimi vertebrati (i primi a subire le pressioni del cambiamento climatico, delle malattie e della frammentazione degli habitat secondo la [IUCN][1]) subisce pesantissime perdite a causa degli investimenti durante l'attraversamento di arterie stradali. Spostandosi spesso in notturna, l'unico modo di ridurre tale impatto è rappresentato spesso dall'azione dei volontari, che con metodi adeguati spostano gli esemplari da una carreggiata all'altra della strada, allo stesso tempo memorizzando i dati del numero individui raccolti.
Save the Prince (http://savetheprince.net) è un progetto originato dalla community [WWF YOUng Italia][0] volto a promuovere e coordinare gli sforzi dei volontari impegnati nei salvataggi degli anfibi dagli investimenti stradali: durante le migrazioni primaverili verso i luoghi di riproduzione, tale classe di sensibilissimi vertebrati (i primi a subire le pressioni del cambiamento climatico, delle malattie e della frammentazione degli habitat secondo la [IUCN][1]) subisce pesantissime perdite a causa degli investimenti durante l'attraversamento di arterie stradali. Spostandosi spesso in notturna, l'unico modo di ridurre tale impatto è rappresentato spesso dall'azione dei volontari, che con metodi adeguati spostano gli esemplari da una carreggiata all'altra della strada, allo stesso tempo memorizzando i dati del numero individui raccolti.
L'azione è supportata da numerose associazioni, tra le quali [WWF Italia][2] e [SOS Anfibi][3].
![logo-wwf-young](/assets/img/young.png "WWF YOUng") ![logo-wwf-italia](assets/img/WWF.png "WWF Italia")
...Per approfondire, c'è pure un [Little Talk][4]!
# Tecnologie
......
......@@ -3,6 +3,7 @@ from django import forms
from django.db.models import Manager
from django.contrib.admin import site as admin_site
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
from django.contrib.admin.filters import RelatedOnlyFieldListFilter
from django.contrib.gis import admin
from django.core.checks.security import sessions
from imagekit.admin import AdminThumbnail
......@@ -16,7 +17,7 @@ from crum import get_current_user
from profiles.models import Profile, BaseProfile
from wwf_prince.utils import *
from .models import Observation, Session, Site, SiteImage, Specie, SpecieImage, ObservationDetail, JournalImage, SiteDoc, SpecieDoc
from .models import Observation, Session, Site, SiteImage, Specie, SpecieImage, ObservationDetail, JournalImage, SiteDoc, SpecieDoc, YearlyReport
class SpecieImageInline(AdminImageMixin, admin.TabularInline):
......@@ -63,11 +64,12 @@ class SiteManager(Manager):
@admin.register(Site)
class SiteAdmin(LeafletGeoAdminMixin, admin.ModelAdmin):
list_display = ('name', 'attivo', 'regione', 'provincia', 'immagine',)
list_display = ('name', 'attivo', 'provincia','comune', 'immagine',)
readonly_fields = ('immagine',)
search_fields = ('name',)
list_filter = ('attivo', 'regione',)
#list_filter = ('attivo', ('regione', RelatedOnlyFieldListFilter),)
list_filter = ('attivo', 'regione','provincia',)
ordering = ('name',)
inlines = [SiteImageInline, SiteDocInline, ]
......@@ -293,3 +295,40 @@ class SessionAdmin(AjaxSelectAdmin):
def get_queryset(self, request):
queryset = SessionManager.get_queryset(self, request)
return queryset
@admin.register(YearlyReport)
class YearlyReportAdmin(admin.ModelAdmin):
list_display = ('site', 'year','date_begin', 'date_end')
readonly_fields = ['created_by', 'modified_by','created','modified']
autocomplete_fields = ['site']
fieldsets = (
# ('Utente', {
# 'fields': (
# ('created_by', 'modified_by',),
# )
# }),
#('',{
# 'fields': (
# ('modified_by','created_by',),
# ('created','modified',),
# )
#}),
('Dettagli generali', {
'fields': (
'site',
'year',
('date_begin', 'date_end',),
('date_barriers_begin', 'date_barriers_end',),
)
}),
('Note', {
'classes': ('collapse', 'closed'),
'fields': (
'andamento',
'note_sito',
'note_traffico',
'note_fauna',
'note_altro',
),
}),
)
\ No newline at end of file
# Generated by Django 2.2 on 2021-05-11 05:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('observations', '0109_auto_20210411_1853'),
]
operations = [
migrations.CreateModel(
name='YearlyReport',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_begin', models.DateField(verbose_name='Data di inizio dei salvataggi')),
('date_end', models.DateField(verbose_name='Data di fine dei salvataggi')),
('date_barriers_begin', models.DateField(verbose_name='Data di posa delle barriere, se presenti')),
('date_barriers_end', models.DateField(verbose_name='Data di rimozione delle barriere, se presenti')),
('year', models.IntegerField(default=2021, verbose_name='Anno')),
('andamento', models.TextField(blank=True, null=True, verbose_name='Andamento generale della migrazione')),
('note_sito', models.TextField(blank=True, null=True, verbose_name='Note relative alla gestione del sito di salvataggio')),
('note_traffico', models.TextField(blank=True, null=True, verbose_name='Note relative al traffico veicolare')),
('note_fauna', models.TextField(blank=True, null=True, verbose_name='Note relative alle particolarità faunistiche')),
('problematiche', models.TextField(blank=True, null=True, verbose_name='Problematiche generali')),
('note_altro', models.TextField(blank=True, null=True, verbose_name='Altre segnalazioni')),
('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='observations.Site', verbose_name='Sito di salvataggio')),
],
options={
'verbose_name': 'Report annuale',
'verbose_name_plural': 'Report annuali',
},
),
]
# Generated by Django 2.2 on 2021-05-11 05:55
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('observations', '0110_yearlyreport'),
]
operations = [
migrations.AddField(
model_name='yearlyreport',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.AddField(
model_name='yearlyreport',
name='created_by',
field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='yearlyreport_added_related', to=settings.AUTH_USER_MODEL, verbose_name='Aggiunto da'),
),
migrations.AddField(
model_name='yearlyreport',
name='modified',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.AddField(
model_name='yearlyreport',
name='modified_by',
field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='yearlyreport_modified_related', to=settings.AUTH_USER_MODEL, verbose_name='Modificato da'),
),
]
# Generated by Django 2.2 on 2021-05-11 06:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('observations', '0111_auto_20210511_0755'),
]
operations = [
migrations.AlterUniqueTogether(
name='yearlyreport',
unique_together={('site', 'year')},
),
]
# Generated by Django 2.2 on 2021-05-13 19:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('observations', '0112_auto_20210511_0803'),
]
operations = [
migrations.AlterField(
model_name='yearlyreport',
name='date_barriers_begin',
field=models.DateField(blank=True, null=True, verbose_name='Data di posa delle barriere, se presenti'),
),
migrations.AlterField(
model_name='yearlyreport',
name='date_barriers_end',
field=models.DateField(blank=True, null=True, verbose_name='Data di rimozione delle barriere, se presenti'),
),
migrations.AlterField(
model_name='yearlyreport',
name='date_begin',
field=models.DateField(verbose_name="Data di inizio dell'attività dei volontari"),
),
migrations.AlterField(
model_name='yearlyreport',
name='date_end',
field=models.DateField(verbose_name="Data di fine dell'attività dei volontari"),
),
]
......@@ -19,7 +19,6 @@ from utils.views import send_email
from django.dispatch import receiver
from django.db.models.signals import pre_save, pre_delete, post_save, post_delete
class Specie(TimeStampedModel):
"""
Memorizza informazioni sulle varie specie
......@@ -403,14 +402,16 @@ class Session(UserReferencedModel, TimeStampedModel):
return "{} - {}, dalle {} alle {}".format(self.site, self.date,
self.begin, self.end)
@property
def volontari_count(self):
if self.volontari:
return self.volontari.count()
@property
def volontari_unregistered_count(self):
if self.volontari_unregistered:
if len(self.volontari_unregistered.split(',')) > 1 and len(self.volontari_unregistered) > 0:
return len(self.volontari_unregistered.split(', '))
return len(self.volontari_unregistered.split(', ')) + 1
else:
return 0
......@@ -648,3 +649,48 @@ class JournalImage(models.Model):
class Meta:
verbose_name = 'Articolo di giornale'
verbose_name_plural = 'Articoli di giornale'
class YearlyReport(UserReferencedModel, TimeStampedModel):
date_begin = models.DateField("Data di inizio dell'attività dei volontari")
date_end = models.DateField("Data di fine dell'attività dei volontari")
date_barriers_begin = models.DateField("Data di posa delle barriere, se presenti",blank=True,null=True)
date_barriers_end = models.DateField("Data di rimozione delle barriere, se presenti",blank=True,null=True)
site = models.ForeignKey(Site,on_delete=models.CASCADE, blank=True, null=True, verbose_name="Sito di salvataggio")
year = models.IntegerField("Anno",default=2021)
andamento = models.TextField("Andamento generale della migrazione",blank=True,null=True)
note_sito = models.TextField("Note relative alla gestione del sito di salvataggio",blank=True,null=True)
note_traffico = models.TextField("Note relative al traffico veicolare",blank=True,null=True)
note_fauna = models.TextField("Note relative alle particolarità faunistiche",blank=True,null=True)
problematiche = models.TextField("Problematiche generali",blank=True,null=True)
note_altro = models.TextField("Altre segnalazioni",blank=True,null=True)
def __str__(self):
return "Report del {} del sito {}".format(self.year, self.site.name)
class Meta:
verbose_name = 'Report annuale'
verbose_name_plural = 'Report annuali'
unique_together = ('site', 'year',)
@property
def volunteers_count(self):
from itertools import chain
session = Session.objects.filter(site=self.site)
volontari_registered = sum([b.volontari.count() for b in session.filter(volontari__isnull=False)])
volontari_unregistered = len(list(chain.from_iterable([b.volontari_unregistered.split(',') for b in session.filter(volontari_unregistered__isnull=False)])))
if volontari_registered and volontari_unregistered:
return volontari_unregistered + volontari_registered
elif volontari_registered and not volontari_unregistered:
return volontari_registered
elif not volontari_registered and volontari_unregistered:
return volontari_unregistered
else:
return 1
@property
def session_count(self):
return Session.objects.filter(site=self.site).count()
# Generated by Django 2.2 on 2021-05-11 05:53
import django.contrib.gis.db.models.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('utils', '0004_auto_20210228_2011'),
]
operations = [
migrations.CreateModel(
name='Comuni',
fields=[
('comuni_id', models.AutoField(db_column='id', primary_key=True, serialize=False, verbose_name='ID')),
('cod_reg', models.CharField(blank=True, max_length=512, null=True, verbose_name='Codice regione')),
('cod_prov', models.CharField(blank=True, max_length=512, null=True, verbose_name='Codice provincia')),
('comune', models.CharField(max_length=512, verbose_name='Nome')),
('geom', django.contrib.gis.db.models.fields.MultiPolygonField(srid=3035, verbose_name='Geometria')),
],
options={
'verbose_name': 'Comune',
'verbose_name_plural': 'Comuni',
'db_table': 'env_data"."comuni',
'managed': False,
},
),
migrations.CreateModel(
name='Province',
fields=[
('province_id', models.AutoField(db_column='id', primary_key=True, serialize=False, verbose_name='ID')),
('cod_reg', models.CharField(blank=True, max_length=512, null=True, verbose_name='Codice regione')),
('cod_prov', models.CharField(blank=True, max_length=512, null=True, verbose_name='Codice provincia')),
('provincia', models.CharField(max_length=512, verbose_name='Nome')),
('geom', django.contrib.gis.db.models.fields.PolygonField(srid=3035, verbose_name='Geometria')),
],
options={
'verbose_name': 'Provincia',
'verbose_name_plural': 'Province',
'db_table': 'env_data"."province',
'managed': False,
},
),
migrations.CreateModel(
name='Regioni',
fields=[
('regioni_id', models.AutoField(db_column='id', primary_key=True, serialize=False, verbose_name='ID')),
('cod_reg', models.CharField(blank=True, max_length=512, null=True, verbose_name='Codice')),
('regione', models.CharField(max_length=512, verbose_name='Nome')),
('geom', django.contrib.gis.db.models.fields.PolygonField(srid=3035, verbose_name='Geometria')),
],
options={
'verbose_name': 'Regione',
'verbose_name_plural': 'Regioni',
'db_table': 'env_data"."regioni',
'managed': False,
},
),
]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment