Remaster (#38)

* setup new 'statistiques' module

* added 'graphos' package and created first test graph

* put graphos in requirements, deleted local folder

* added "load_csv" management command !

* added update of premiere_rencontre field in 'load_csv' management command

* added missing urls.py file

* added 'merge' action and view

* added 'info_completed' ratio

* linked sujets:merge views inside suivi:details

* added link to maraudes:details in notes table headers, if any

* Major reorganisation, moved 'suivi' and 'sujets' to 'notes', cleanup in 'maraudes', dropping 'website' mixins (mostly useless)

* small cleanup

* worked on Maraude and Sujet lists

* corrected missing line in notes.__init__

* restored 'details' view for maraudes and sujets insie 'notes' module

* worked on 'notes': added navigation between maraude's compte-rendu, right content in details, header to list tables

* changed queryset for CompteRenduDetailsView to all notes of same date, minor layout changes

* added right content to 'details-sujet', created 'statistiques' view and update templates

* restored 'statistiques' ajax view in 'details-sujet', fixed 'merge_two' util function

* added auto-creation of FicheStatistique (plus some tests), pagination for notes in 'details-sujet'

* added error-prone cases in paginator

* fixed non-working modals, added titles

* added UpdateStatistiques capacity in CompteRenduCreate view

* fixed missing AjaxTemplateMixin for CreateSujetView, worked on compte-rendu creation scripts

* fixed MaraudeManager.all_of() for common Maraudeurs, added color hints in planning

* re-instated statistiques module link and first test page

* added FinalizeView to send a mail before finalizing compte-rendu

* Added PieChart view for FicheStatistique fields

* small style updates, added 'age' and 'genre' fields from sujets in statistiques.PieChartView

* worked on statistiques, fixed small issues in 'notes' list views

* small theme change

* removed some dead code

* fixed notes.tests, fixed statistiques.info_completed display, added filter in SujetLisView

* added some tests

* added customised admin templates

* added authenticate in CustomAuthenticatationBackend, more verbose login thanks to messages

* added django-nose for test coverage

* Corrected raising exception on first migration

On first migration, qs.exists() would previously be called and raising an Exception, sot he migrations would fail.

* Better try block

* cleaned up custom settings.py, added some overrides of django base_settings

* corrected bad dictionnary key
This commit is contained in:
artus40
2017-06-11 17:16:17 +02:00
committed by GitHub
parent 0be59a61a7
commit be087464fc
155 changed files with 3568 additions and 1988 deletions

View File

@@ -1,25 +1,37 @@
import datetime
from django.db import models
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from django.contrib.auth.models import User, UserManager, AnonymousUser
from django.db import models
from django.contrib.auth.models import User
from .managers import MaraudeurManager
# Create your models here.
if not settings.MARAUDEURS:
raise ImproperlyConfigured("No configuration for Maraudeur model")
else:
try:
assert(isinstance(settings.MARAUDEURS.get('organisme'), dict))
except:
raise ImproperlyConfigured("'organisme' key of MARAUDEURS settings is not a dict !")
## Visiteur
class Visiteur(AnonymousUser):
def get_email_suffix(organisme):
if not organisme.email:
return "unconfigured.org"
else:
return organisme.email.split("@")[1]
def __str__(self):
return "Visiteur"
class Organisme(models.Model):
""" Organisme : Association, Entreprise, Service public, ..."""
nom = models.CharField(max_length=64)
nom = models.CharField(max_length=64, primary_key=True)
email = models.EmailField("e-mail")
adresse = models.CharField(max_length=128)
adresse = models.CharField(max_length=128, blank=True, null=True)
class Meta:
verbose_name = "Organisme"
@@ -31,70 +43,50 @@ class Organisme(models.Model):
class Professionnel(User):
""" Professionnel d'un organisme """
organisme = models.ForeignKey(
Organisme,
organisme = models.ForeignKey(Organisme,
models.CASCADE,
related_name="professionnels",
blank=True, null=True # For now
)
def make_username(self):
""" Build the username for this Professionel instance. Must be overriden."""
raise NotImplementedError
class MaraudeurManager(UserManager):
""" Manager for Maraudeurs objects.
Updates `create`, `get_or_create` methods signatures : 'first_name', 'last_name'.
Add `set_referent` method (same signature).
"""
def create(self, first_name, last_name):
username = "%s.%s" % (first_name[0].lower(), last_name.lower())
data = {
'first_name': first_name,
'last_name': last_name,
'email': "%s@alsa68.org" % username,
'is_staff': True,
'is_active': True,
}
return super().create_user(username, **data)
def get_or_create(self, first_name, last_name):
try:
maraudeur = self.get(first_name=first_name, last_name=last_name)
created = False
except self.model.DoesNotExist:
created = True
maraudeur = self.create(first_name, last_name)
return (maraudeur, created)
def get_referent(self):
try:
return self.get(is_superuser=True)
except self.model.DoesNotExist:
return None
def set_referent(self, first_name, last_name):
maraudeur, created = self.get_or_create(first_name, last_name)
for previous in self.get_queryset().filter(is_superuser=True):
previous.is_superuser = False
previous.save()
maraudeur.is_superuser = True
maraudeur.save()
return maraudeur
def save(self, *args, **kwargs):
self.username = self.make_username()
if not self.pk:
self.email = "%s@%s" % (self.username, get_email_suffix(self.organisme))
return super().save(*args, **kwargs)
class Maraudeur(Professionnel):
""" Professionnels qui participent aux maraudes """
""" Professionnel qui participe aux maraudes """
# Donne accès aux vues "maraudes" et "suivi"
@staticmethod
def get_organisme():
return Organisme.objects.get_or_create(**settings.MARAUDEURS['organisme'])[0]
def est_referent(self):
return self.is_superuser
est_referent.boolean = True
est_referent.short_description = 'Référent Maraude'
objects = MaraudeurManager()
class Meta:
verbose_name = "Maraudeur"
def __str__(self):
return "%s %s" % (self.first_name, self.last_name[0])
def make_username(self):
return "%s.%s" % (self.first_name[0].lower(), self.last_name.lower())
def save(self, *args, **kwargs):
if not self.pk:
self.is_staff = True
self.organisme = Maraudeur.get_organisme()
self.set_password(settings.MARAUDEURS['password'])
return super().save(*args, **kwargs)
def __str__(self):
return "%s %s." % (self.first_name, self.last_name[0])