2911 lines
130 KiB
Python
2911 lines
130 KiB
Python
import os
|
||
import shutil
|
||
import tempfile
|
||
from datetime import date, timedelta
|
||
from pathlib import Path
|
||
from unittest import skip
|
||
from unittest.mock import patch
|
||
|
||
from freezegun import freeze_time
|
||
|
||
from django.conf.global_settings import PASSWORD_HASHERS
|
||
from django.contrib.auth.models import Group, Permission
|
||
from django.core.files import File
|
||
from django.db.utils import IntegrityError
|
||
from django.forms import Form
|
||
from django.forms.models import model_to_dict
|
||
from django.test import RequestFactory, TestCase, tag
|
||
from django.test.utils import override_settings
|
||
from django.urls import reverse
|
||
|
||
from .export import ExportReporting, openxml_contenttype
|
||
from .forms import (
|
||
AgendaForm, FamilleCreateForm, HMDurationField, NiveauForm, PersonneForm,
|
||
PrestationForm, UtilisateurForm
|
||
)
|
||
from .models import (
|
||
Bilan, CercleScolaire, Contact, EtapeFin, Famille, Formation, Intervenant,
|
||
JournalAcces, LibellePrestation, Niveau, Personne, Prestation, Rapport, Region, Role,
|
||
Service, Suivi, Utilisateur,
|
||
)
|
||
from .utils import ANTICIPATION_POUR_DEBUT_SUIVI, format_duree, format_d_m_Y
|
||
from .views_stats import Month, StatistiquesView
|
||
|
||
|
||
class InitialDataMixin:
|
||
@classmethod
|
||
def setUpTestData(cls):
|
||
s1, _ = Service.objects.get_or_create(sigle='CRXNE')
|
||
Service.objects.bulk_create([
|
||
Service(sigle='OPEN'),
|
||
Service(sigle='SSE')
|
||
])
|
||
|
||
CercleScolaire.objects.bulk_create([
|
||
CercleScolaire(nom='EOREN-MAIL'),
|
||
CercleScolaire(nom='EOCF-NUMA-DROZ')
|
||
])
|
||
|
||
grp_aemo = Group.objects.create(name='aemo')
|
||
grp_aemo.permissions.add(*list(
|
||
Permission.objects.filter(codename__in=[
|
||
'view_famille', 'add_famille', 'add_prestation'
|
||
])
|
||
))
|
||
|
||
Role.objects.bulk_create([
|
||
Role(nom='Père', est_famille=True),
|
||
Role(nom='Mère', est_famille=True),
|
||
Role(nom='Beau-père', est_famille=True),
|
||
Role(nom='Enfant suivi', est_famille=True),
|
||
Role(nom='Enfant non-suivi', est_famille=True),
|
||
Role(nom='Médecin', est_famille=False),
|
||
Role(nom='Psy', est_famille=False, est_intervenant=True, est_editeur=True),
|
||
Role(nom='Educ', est_famille=False, est_intervenant=True, est_editeur=True),
|
||
Role(nom='Assistant-e social-e', est_famille=False, est_intervenant=True),
|
||
Role(nom='Référent', est_famille=False),
|
||
])
|
||
|
||
Contact.objects.bulk_create([
|
||
Contact(nom='Sybarnez', prenom='Tina', tel_prof='032 886 88 88', service=s1),
|
||
Contact(nom='Rathfeld', prenom='Christophe', service=Service.objects.get(sigle='OPEN')),
|
||
Contact(nom='DrSpontz', prenom='Igor'),
|
||
])
|
||
Contact.objects.get(nom='DrSpontz').roles.add(Role.objects.get(nom='Médecin'))
|
||
|
||
Region.objects.bulk_create([
|
||
Region(nom='Littoral Est'),
|
||
Region(nom='Littoral Ouest'),
|
||
Region(nom='Montagnes'),
|
||
Region(nom='Val-de-Ruz'),
|
||
Region(nom='Val-de-Travers'),
|
||
], ignore_conflicts=True)
|
||
|
||
LibellePrestation.objects.bulk_create([
|
||
LibellePrestation(code='aemo01', nom='Évaluation'),
|
||
LibellePrestation(code='aemo02', nom='Accompagnement'),
|
||
LibellePrestation(code='aemo03', nom='Prestation gén.'),
|
||
LibellePrestation(code='aemo04', nom='Activités ASE'),
|
||
])
|
||
|
||
grp_admin = Group.objects.create(name='admin')
|
||
grp_admin.permissions.add(*Permission.objects.filter(codename__in=[
|
||
'add_role', 'change_role', 'delete_role', 'add_service',
|
||
'add_utilisateur', 'change_utilisateur', 'delete_utilisateur',
|
||
'view_famille', 'change_famille', 'export_stats'
|
||
]))
|
||
cls.aemo_group = Group.objects.get(name='aemo')
|
||
cls.aemo_group.permissions.add(Permission.objects.get(codename='add_famille'))
|
||
cls.user_admin = Utilisateur.objects.create_user(
|
||
'user_admin', 'user_admin@example.com', nom='Admin', prenom='Prénom', sigle='ADM'
|
||
)
|
||
cls.user_admin.groups.add(grp_admin)
|
||
cls.user_admin.groups.add(cls.aemo_group)
|
||
resp = Role.objects.create(nom='Responsable/coordinateur')
|
||
cls.user_admin.roles.add(resp)
|
||
|
||
cls.user_aemo = Utilisateur.objects.create_user(
|
||
'user_aemo', 'user_aemo@example.org', nom='Aemo', prenom='Prénom', sigle='SP', taux_activite=60,
|
||
)
|
||
cls.user_aemo.roles.add(Role.objects.get(nom='Educ'))
|
||
cls.user_aemo2 = Utilisateur.objects.create_user(
|
||
'user_aemo2', 'user_aemo2@example.org', nom='Aemo2', prenom='Prénom', sigle='SP2'
|
||
)
|
||
cls.user_aemo2.roles.add(Role.objects.get(nom='Psy'))
|
||
cls.user_aemo.groups.add(cls.aemo_group)
|
||
cls.user_aemo2.groups.add(cls.aemo_group)
|
||
|
||
cls.user_externe = Utilisateur.objects.create_user(
|
||
'externe', 'externe@example.org', 'mepassword', prenom='Bruce', nom='Externe',
|
||
)
|
||
cls.create_famille()
|
||
|
||
@classmethod
|
||
def create_famille(cls, name='Haddock'):
|
||
famille = Famille.objects.create_famille(
|
||
nom=name, rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes', autorite_parentale='conjointe', statut_marital='divorce', monoparentale=False
|
||
)
|
||
pere = Role.objects.get(nom='Père')
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=pere,
|
||
nom=name, prenom='Archibald', genre='M', date_naissance=date(1956, 2, 16),
|
||
rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
famille.suivi.ope_referent = Contact.objects.get(nom="Sybarnez")
|
||
famille.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom=name, prenom='Toto', genre='M', date_naissance=date(2010, 2, 16),
|
||
rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
return famille
|
||
|
||
|
||
class TempMediaRootMixin:
|
||
@classmethod
|
||
def setUpClass(cls):
|
||
cls._temp_media = tempfile.mkdtemp()
|
||
cls._overridden_settings = cls._overridden_settings or {}
|
||
cls._overridden_settings['MEDIA_ROOT'] = cls._temp_media
|
||
super().setUpClass()
|
||
|
||
@classmethod
|
||
def tearDownClass(cls):
|
||
shutil.rmtree(cls._temp_media)
|
||
super().tearDownClass()
|
||
|
||
|
||
class FamilleTests(InitialDataMixin, TestCase):
|
||
personne_data = {
|
||
'nom': 'Dupont',
|
||
'prenom': 'Jean',
|
||
'date_naissance': '1950-03-30',
|
||
'genre': 'M',
|
||
}
|
||
famille_data = {
|
||
'nom': 'Dupont',
|
||
'rue': 'Rue du Moulins',
|
||
'npa': '3000',
|
||
'localite': 'Paris',
|
||
'autorite_parentale': 'conjointe',
|
||
'equipe': 'montagnes',
|
||
}
|
||
|
||
def setUp(self):
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
def test_acces(self):
|
||
"""
|
||
Sans permission adaptée, un utilisateur ne peut pas accéder à certaines
|
||
pages (création de famille, etc.).
|
||
"""
|
||
user = Utilisateur.objects.create_user(
|
||
'qqun', 'qqun@example.org', 'pwd', first_name='Qqun', last_name='Personne',
|
||
)
|
||
self.client.force_login(user)
|
||
with self.assertLogs('django.request', level='WARNING'):
|
||
response = self.client.get(reverse('famille-add'))
|
||
self.assertEqual(response.status_code, 403)
|
||
|
||
def test_personne_creation(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
add_url = reverse('personne-add', args=[famille.pk])
|
||
response = self.client.get(add_url)
|
||
self.assertEqual(response.context['form'].initial['nom'], famille.nom)
|
||
|
||
# Données minimales: nom, genre, rôle
|
||
role = Role.objects.get(nom='Beau-père')
|
||
response = self.client.post(add_url, data={'nom': 'Smith', 'genre': 'M', 'role': role.pk})
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]))
|
||
response = self.client.post(
|
||
add_url,
|
||
data={**self.personne_data, 'role': Role.objects.get(nom='Beau-père').pk, 'localite': "bevaix"}
|
||
)
|
||
self.assertEqual(response.status_code, 302)
|
||
self.assertQuerySetEqual(Personne.objects.all(), [
|
||
'<Personne: Dupont Jean>',
|
||
'<Personne: Haddock Archibald>',
|
||
'<Personne: Haddock Toto>',
|
||
'<Personne: Smith >',
|
||
], transform=repr)
|
||
p1 = Personne.objects.get(nom='Dupont')
|
||
self.assertEqual(p1.famille, famille)
|
||
self.assertEqual(p1.localite, 'Bevaix')
|
||
with self.assertRaises(Formation.DoesNotExist):
|
||
p1.formation
|
||
|
||
# Personne < 4 ans
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
date_naissance=date.today() - timedelta(days=720),
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
self.assertEqual(pers.formation.get_statut_display(), 'Pré-scolaire')
|
||
self.assertTrue(famille.suivi.demande_prioritaire)
|
||
|
||
def test_label_profession_variable(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
response = self.client.get(
|
||
'{}?role={}'.format(reverse('personne-add', args=[famille.pk]),
|
||
Role.objects.get(nom='Enfant suivi').pk)
|
||
)
|
||
self.assertContains(response, '<label for="id_profession">Profession/École :</label>', html=True)
|
||
|
||
response = self.client.get(
|
||
'{}?role={}'.format(reverse('personne-add', args=[famille.pk]),
|
||
Role.objects.get(nom='Père').pk)
|
||
)
|
||
self.assertContains(response, '<label for="id_profession">Profession :</label>', html=True)
|
||
|
||
def test_get_membres(self):
|
||
# Obtention des différents membres avec 2 requêtes: la famille, les membres (prefetch_related)
|
||
with self.assertNumQueries(2):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
self.assertEqual(famille.membres_suivis()[0].prenom, 'Toto')
|
||
self.assertEqual(famille.enfants_non_suivis(), [])
|
||
self.assertEqual([p.nom_prenom for p in famille.parents()], ['Haddock Archibald'])
|
||
self.assertEqual(famille.autres_parents(), [])
|
||
|
||
def test_personne_age(self):
|
||
with patch('aemo.models.date') as mock_date:
|
||
mock_date.today.return_value = date(2019, 1, 16)
|
||
self.assertEqual(Personne(date_naissance=date(1999, 11, 4)).age, 19.2)
|
||
self.assertEqual(Personne(date_naissance=date(2000, 1, 1)).age, 19.0)
|
||
self.assertEqual(Personne(date_naissance=date(2000, 1, 31)).age, 18.9)
|
||
|
||
def test_personne_age_str(self):
|
||
pers = Personne(prenom='Toto')
|
||
pers.date_naissance = date.today() - timedelta(days=12)
|
||
self.assertEqual(pers.age_str(), '12 jours')
|
||
pers.date_naissance = date.today() - timedelta(days=33)
|
||
self.assertEqual(pers.age_str(), '4 sem. 5 jours')
|
||
pers.date_naissance = date.today() - timedelta(days=77)
|
||
self.assertEqual(pers.age_str(), '2 mois 2 sem.')
|
||
pers.date_naissance = date.today() - timedelta(days=689)
|
||
self.assertEqual(pers.age_str(), '22 mois 4 sem.')
|
||
pers.date_naissance = date.today() - timedelta(days=690)
|
||
self.assertEqual(pers.age_str(), '1 an 10 mois')
|
||
pers.date_naissance = date.today() - timedelta(days=691)
|
||
self.assertEqual(pers.age_str(format_='jour'), '691 jours')
|
||
|
||
def test_personne_edition(self):
|
||
famille = Famille.objects.create_famille(nom='Dupont', equipe='montagnes')
|
||
pers_data = dict(self.personne_data, famille=famille.pk, role=Role.objects.get(nom='Père').pk)
|
||
form = PersonneForm(data=pers_data, famille=famille)
|
||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||
pers = form.save()
|
||
edit_url = reverse('personne-edit', args=[famille.pk, pers.pk])
|
||
new_data = dict(pers_data, rue='Rue du Parc 12')
|
||
response = self.client.post(edit_url, data=new_data)
|
||
self.assertEqual(response.status_code, 302)
|
||
pers.refresh_from_db()
|
||
self.assertEqual(pers.rue, 'Rue du Parc 12')
|
||
# Edition is refused if user is missing the permission
|
||
user = Utilisateur.objects.create_user(
|
||
'joe', 'joe@example.org', 'pwd', first_name='Joe', last_name='Cook',
|
||
)
|
||
self.client.force_login(user)
|
||
with self.assertLogs('django.request', level='WARNING'):
|
||
response = self.client.get(edit_url)
|
||
self.assertEqual(response.status_code, 403)
|
||
|
||
def test_personne_formation(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
self.assertTrue(famille.can_edit(self.user_aemo))
|
||
form_url = reverse('formation', args=[pers.pk])
|
||
response = self.client.get(form_url)
|
||
self.assertFalse(response.context['form'].readonly)
|
||
self.assertContains(response, "Enregistrer")
|
||
response = self.client.post(form_url, data={
|
||
'statut': 'cycle2',
|
||
'cercle_scolaire': CercleScolaire.objects.first().pk,
|
||
'college': 'École parfaite',
|
||
'classe': '6H',
|
||
})
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]))
|
||
pers.refresh_from_db()
|
||
self.assertEqual(pers.formation.classe, '6H')
|
||
|
||
def test_delete_personne_formation_impossible(self):
|
||
pers = Personne.objects.create_personne(
|
||
famille=Famille.objects.first(), prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
self.assertRaises(IntegrityError, pers.formation.delete)
|
||
|
||
def test_delete_personne(self):
|
||
famille = Famille.objects.first()
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Père')
|
||
)
|
||
response = self.client.post(
|
||
reverse('personne-delete', args=[famille.pk, pers.pk]), follow=True
|
||
)
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]), status_code=302)
|
||
|
||
def test_famille_creation(self):
|
||
response = self.client.get(reverse('famille-add'))
|
||
self.assertContains(response, '<option value="montagnes">Montagnes et V-d-T</option>', html=True)
|
||
self.assertContains(
|
||
response,
|
||
'<button class="btn btn-sm btn-success" name="save" type="submit">Enregistrer</button>',
|
||
html=True
|
||
)
|
||
self.assertContains(response, "id_motif_detail")
|
||
response = self.client.post(reverse('famille-add'), data={
|
||
**self.famille_data, 'motif_detail': "Un test parmi d'autres"
|
||
})
|
||
famille = Famille.objects.get(nom='Dupont')
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]))
|
||
famille = Famille.objects.get(nom='Dupont')
|
||
self.assertEqual(famille.suivi.equipe, 'montagnes')
|
||
self.assertEqual(famille.suivi.date_demande, date.today())
|
||
self.assertEqual(famille.suivi.motif_detail, "Un test parmi d'autres")
|
||
|
||
def test_famille_edition(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
edit_url = reverse('famille-edit', args=[famille.pk])
|
||
response = self.client.get(edit_url)
|
||
self.assertContains(response, '<select name="provenance" class="form-select" id="id_provenance">')
|
||
self.assertContains(response, reverse('print-coord-famille', args=[famille.pk]))
|
||
self.assertContains(response, "Changer l’adresse")
|
||
self.assertNotContains(response, "id_motif_detail")
|
||
data = {**self.famille_data, 'localite': 'Monaco'}
|
||
response = self.client.post(edit_url, data=data)
|
||
self.assertRedirects(response, edit_url)
|
||
famille.refresh_from_db()
|
||
self.assertEqual(famille.localite, 'Monaco')
|
||
|
||
def test_famille_edition_perm(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
user_1 = Utilisateur.objects.create(username='jean')
|
||
user_1.groups.add(Group.objects.get(name='aemo'))
|
||
user_2 = Utilisateur.objects.create(username='ben')
|
||
user_2.groups.add(Group.objects.get(name='aemo'))
|
||
manager = Utilisateur.objects.create(username='boss')
|
||
manager.user_permissions.add(Permission.objects.get(codename='change_famille'))
|
||
manager2 = Utilisateur.objects.create(username='boss2')
|
||
manager2.roles.add(Role.objects.get(nom='Responsable/coordinateur'))
|
||
# No referent set, any team user can edit
|
||
self.assertTrue(famille.can_edit(user_1))
|
||
interv = Intervenant.objects.create(
|
||
suivi=famille.suivi, intervenant=user_2, role=Role.objects.get(nom='Educ'),
|
||
date_debut=date.today() - timedelta(days=3)
|
||
)
|
||
# Only referent (or manager) can access
|
||
self.assertFalse(famille.can_edit(user_1))
|
||
self.assertTrue(famille.can_edit(user_2))
|
||
self.assertTrue(famille.can_edit(manager))
|
||
self.assertTrue(famille.can_edit(manager2))
|
||
interv.date_fin = date.today() - timedelta(days=1)
|
||
self.assertTrue(famille.can_edit(user_2))
|
||
|
||
def test_famille_list(self):
|
||
reg_montagnes = Region.objects.get_or_create(nom='Montagnes')[0]
|
||
reg_litt_ouest = Region.objects.get_or_create(nom='Littoral Ouest')[0]
|
||
fam1 = Famille.objects.get(nom='Haddock')
|
||
fam2 = Famille.objects.create_famille(
|
||
nom='Dupond', rue='Château 4', npa=2299, localite='Klow',
|
||
region=reg_montagnes, equipe='montagnes',
|
||
)
|
||
fam2.suivi.date_debut_evaluation = date.today() - timedelta(days=3)
|
||
fam2.suivi.save()
|
||
fam2.suivi.intervenants.add(self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')})
|
||
Niveau.objects.create(famille=fam2, niveau_interv=1, date_debut=date.today())
|
||
# famille sans équipe
|
||
Famille.objects.create_famille(
|
||
nom='Sprutz', rue='Fleur 12', npa=2299, localite='Klow',
|
||
region=reg_montagnes, equipe='montagnes'
|
||
)
|
||
Famille.objects.create_famille(
|
||
nom='Tournesol', rue='Château1', npa=2000, localite='Moulinsart',
|
||
region=reg_litt_ouest, equipe='littoral',
|
||
)
|
||
response = self.client.get(reverse('famille-list'))
|
||
self.assertEqual(len(response.context['object_list']), Famille.objects.count())
|
||
self.assertContains(
|
||
response,
|
||
'<a href="%s" title="Suivi">Haddock</a>' % reverse('famille-suivi', args=[fam1.pk]),
|
||
html=True
|
||
)
|
||
# Apply filters
|
||
response = self.client.get(
|
||
reverse('famille-list') + '?equipe=montagnes&niveau=1&nom=du'
|
||
)
|
||
self.assertEqual(response.context['form'].errors, {})
|
||
self.assertQuerySetEqual(response.context['object_list'], [fam2])
|
||
# All levels
|
||
response = self.client.get(reverse('famille-list') + '?niveau=')
|
||
self.assertEqual(len(response.context['object_list']), 4)
|
||
|
||
# Liste d'attente
|
||
response = self.client.get(reverse('famille-attente'))
|
||
self.assertEqual(len(response.context['object_list']), 4)
|
||
self.assertContains(response, f'<td>{reg_montagnes.nom}</td>', html=True)
|
||
self.assertContains(response, '<td class="red">À faire</td>', html=True)
|
||
|
||
response = self.client.get(reverse('famille-attente') + '?equipe=littoral')
|
||
self.assertEqual(len(response.context['object_list']), 1)
|
||
|
||
response = self.client.get(reverse('famille-attente') + '?equipe=montagnes')
|
||
self.assertEqual(len(response.context['object_list']), 3)
|
||
|
||
def test_famille_list_filtre_intervenant(self):
|
||
fam1 = Famille.objects.get(nom='Haddock')
|
||
# Ajout intervention passée
|
||
fam1.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={
|
||
'role': Role.objects.get(nom='Educ'), 'date_fin': date.today() - timedelta(days=3)
|
||
}
|
||
)
|
||
fam2 = Famille.objects.create_famille(
|
||
nom='Dupond', rue='Château 4', npa=2299, localite='Klow', equipe='montagnes',
|
||
)
|
||
fam2.suivi.date_debut_evaluation = date.today() - timedelta(days=3)
|
||
fam2.suivi.save()
|
||
fam2.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')}
|
||
)
|
||
response = self.client.get(reverse('famille-list') + f'?&interv={self.user_aemo.pk}')
|
||
self.assertEqual(response.context['form'].errors, {})
|
||
self.assertQuerySetEqual(response.context['object_list'], [fam2])
|
||
# Familles sans intervenant
|
||
response = self.client.get(reverse('famille-list') + '?interv=0')
|
||
self.assertQuerySetEqual(response.context['object_list'], [fam1])
|
||
self.assertEqual(response.context['object_list'][0].suivi.intervenant_set.count(), 0)
|
||
|
||
def test_calcul_charge_liste_famille(self):
|
||
fam1 = Famille.objects.get(nom='Haddock')
|
||
fam1.suivi.date_debut_suivi = date.today()
|
||
fam1.suivi.save()
|
||
fam1.suivi.intervenants.add(self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')})
|
||
Niveau.objects.create(famille=fam1, niveau_interv=2, date_debut=date.today())
|
||
|
||
fam2 = Famille.objects.create_famille(
|
||
nom='Dupond', rue='Château 4', npa=2299, localite='Klow',
|
||
)
|
||
fam2.suivi.date_debut_evaluation = date.today() - timedelta(days=3)
|
||
fam2.suivi.heure_coord = True
|
||
fam2.suivi.save()
|
||
fam2.suivi.intervenants.add(self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')})
|
||
Niveau.objects.create(famille=fam2, niveau_interv=1, date_debut=date.today())
|
||
|
||
fam3 = Famille.objects.create_famille(
|
||
nom='Dupond2', rue='Château 4', npa=2299, localite='Klow',
|
||
)
|
||
fam3.suivi.date_debut_evaluation = date.today() - timedelta(days=3)
|
||
fam3.suivi.save()
|
||
fam3.suivi.intervenants.add(self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')})
|
||
Niveau.objects.create(famille=fam3, niveau_interv=3, date_debut=date.today())
|
||
|
||
# Ne doit pas compter car intervention terminée
|
||
fam4 = Famille.objects.create_famille(
|
||
nom='Dupond3', rue='Château 6', npa=2299, localite='Klow',
|
||
)
|
||
fam4.suivi.date_debut_evaluation = date.today() - timedelta(days=3)
|
||
fam4.suivi.save()
|
||
fam4.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={
|
||
'role': Role.objects.get(nom='Educ'), 'date_fin': date.today() - timedelta(days=1),
|
||
}
|
||
)
|
||
Niveau.objects.create(famille=fam4, niveau_interv=2, date_debut=date.today())
|
||
|
||
response = self.client.get(reverse('famille-list'))
|
||
self.assertEqual(
|
||
response.context['ma_charge'],
|
||
{'heures': 9, 'nbre_eval': 2, 'nbre_suivi': 1, 'charge_diff': 7}
|
||
)
|
||
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('charge-utilisateurs'))
|
||
self.assertEqual(response.context['utilisateurs'], [self.user_aemo, self.user_aemo2])
|
||
self.assertEqual(response.context['utilisateurs'][0].charge, 8)
|
||
self.assertEqual(response.context['utilisateurs'][0].heures, 9)
|
||
self.assertEqual(response.context['utilisateurs'][0].nbre_suivi, 1)
|
||
self.assertEqual(response.context['utilisateurs'][0].nbre_eval, 2)
|
||
self.assertEqual(response.context['utilisateurs'][1].charge, 0)
|
||
self.assertEqual(response.context['utilisateurs'][1].heures, 0)
|
||
self.assertEqual(response.context['utilisateurs'][1].nbre_suivi, 0)
|
||
self.assertEqual(response.context['utilisateurs'][1].nbre_eval, 0)
|
||
|
||
def test_delete_enfant_suivi(self):
|
||
famille = Famille.objects.first()
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
with self.assertLogs('django.request', level='WARNING'):
|
||
response = self.client.post(reverse('personne-delete', args=[famille.pk, pers.pk]), follow=True)
|
||
self.assertTrue(response.status_code, 403)
|
||
|
||
def test_affichage_familles_libres_pour_tous_les_educs(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes'
|
||
)
|
||
self.assertEqual(famille.suivi.intervenants.count(), 0)
|
||
response = self.client.get(reverse('famille-list'))
|
||
self.assertContains(response, 'Simpson')
|
||
|
||
def test_affichage_adresse(self):
|
||
famille = Famille(nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart')
|
||
self.assertEqual(famille.adresse, 'Château1, 2000 Moulinsart')
|
||
famille.rue = ''
|
||
self.assertEqual(famille.adresse, '2000 Moulinsart')
|
||
famille.npa = ''
|
||
self.assertEqual(famille.adresse, 'Moulinsart')
|
||
|
||
def test_acces_lecture_seule_famille_archivee(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
famille.suivi.date_fin_suivi = '2020-04-15'
|
||
famille.suivi.save()
|
||
response = self.client.get(reverse('famille-suivi', args=[famille.pk]))
|
||
self.assertFalse(response.context['can_edit'])
|
||
response = self.client.get(reverse('famille-edit', args=[famille.pk]))
|
||
self.assertFalse(response.context['can_edit'])
|
||
response = self.client.get(reverse('personne-edit', args=[famille.pk, famille.membres.first().pk]))
|
||
self.assertTrue(response.context['form'].fields['nom'].disabled)
|
||
# Changement adresse impossible
|
||
response = self.client.get(reverse('famille-adresse-change', args=[famille.pk]))
|
||
self.assertEqual(response.status_code, 403)
|
||
|
||
def test_affichage_bouton_changement_adresse(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
response = self.client.get(reverse('famille-edit', args=[famille.pk]))
|
||
url = reverse('famille-adresse-change', args=[famille.pk])
|
||
self.assertContains(
|
||
response,
|
||
f'<a class="btn btn-sm btn-outline-primary" href="{url}">Changer l’adresse</a>',
|
||
html=True
|
||
)
|
||
|
||
def test_membres_famille_dans_form_changement_adresse(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe', rue='Fleurs 44',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
edit_url = reverse('famille-adresse-change', args=[famille.pk])
|
||
response = self.client.get(edit_url)
|
||
self.assertContains(response, 'Lagaffe Gaston (Enfant suivi)')
|
||
self.assertContains(response, 'Haddock Archibald (Père)')
|
||
|
||
data = {'rue': 'Champs-Elysées 1', 'npa': '7500', 'localite': 'Paris', 'membres': [pers.pk]}
|
||
response = self.client.post(edit_url, data=data)
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]))
|
||
pers.refresh_from_db()
|
||
self.assertEqual(pers.rue, "Champs-Elysées 1")
|
||
for parent in famille.parents():
|
||
self.assertEqual(parent.rue, 'Château1')
|
||
# Test changement adresse sans changer pour les membres
|
||
data = {'rue': 'Champs-Elysées 2', 'npa': '7500', 'localite': 'Paris', 'membres': []}
|
||
response = self.client.post(edit_url, data=data)
|
||
self.assertRedirects(response, reverse('famille-edit', args=[famille.pk]))
|
||
|
||
def test_nom_famille_formatage(self):
|
||
form = FamilleCreateForm(data={'nom': 'dubois', 'equipe': 'montagnes'})
|
||
self.assertTrue(form.is_valid())
|
||
form.save()
|
||
self.assertTrue(Famille.objects.filter(nom='Dubois').exists())
|
||
|
||
form = FamilleCreateForm(data={'nom': 'de Gaule', 'equipe': 'montagnes'})
|
||
self.assertTrue(form.is_valid())
|
||
form.save()
|
||
self.assertTrue(Famille.objects.filter(nom='de Gaule').exists())
|
||
|
||
def test_nom_personne_formatage(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.get(nom='Haddock', prenom='Archibald')
|
||
edit_url = reverse('personne-edit', args=[famille.pk, pers.pk])
|
||
self.client.post(
|
||
edit_url,
|
||
data={'nom': 'doe', 'prenom': 'john', 'role': pers.role.pk, 'genre': 'M'},
|
||
follow=True
|
||
)
|
||
doe = Personne.objects.get(nom='Doe', prenom='John')
|
||
self.assertEqual(pers.pk, doe.pk)
|
||
|
||
def test_interventions_actives(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
educ = Role.objects.get(nom='Educ')
|
||
today = date.today()
|
||
date_passe = today - timedelta(days=30)
|
||
date_futur = today + timedelta(days=30)
|
||
int1, int2, int3, int4 = Intervenant.objects.bulk_create([
|
||
Intervenant(
|
||
suivi=famille.suivi, intervenant=self.user_aemo, role=educ,
|
||
date_debut=debut, date_fin=fin
|
||
) for debut, fin in [
|
||
(date_passe, date_passe + timedelta(days=5)), # complètement passé
|
||
(date_futur, None), # futur
|
||
(date_passe, date_futur),
|
||
(date_passe, None),
|
||
]
|
||
])
|
||
self.assertQuerySetEqual(famille.interventions_actives().order_by('pk'), [int3, int4])
|
||
self.assertQuerySetEqual(famille.interventions_actives(today - timedelta(days=31)), [])
|
||
|
||
def test_ajout_intervenant(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
intervenant = self.user_aemo
|
||
role = Role.objects.get(nom='Educ')
|
||
date_debut = date.today()
|
||
response = self.client.post(
|
||
reverse('intervenant-add', args=[famille.pk]),
|
||
data={'intervenant': intervenant.pk, 'role': role.pk, 'date_debut': date_debut}
|
||
)
|
||
self.assertRedirects(response, reverse('famille-suivi', args=[famille.pk]))
|
||
self.assertTrue(
|
||
Intervenant.objects.filter(
|
||
suivi=famille.suivi, intervenant=intervenant, role=role, date_debut=date_debut
|
||
).exists()
|
||
)
|
||
|
||
def test_modif_intervenant(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
intervenant = self.user_aemo
|
||
role = Role.objects.get(nom='Educ')
|
||
date_debut = date.today()
|
||
intervention = Intervenant.objects.create(
|
||
suivi=famille.suivi, intervenant=intervenant, role=role, date_debut=date_debut
|
||
)
|
||
suivi_url = reverse('famille-suivi', args=[famille.pk])
|
||
add_url = reverse("intervenant-add", args=[famille.pk])
|
||
edit_url = reverse("intervenant-edit", args=[famille.pk, intervention.pk])
|
||
response = self.client.get(suivi_url)
|
||
# Test boutons ajouter/modifier
|
||
self.assertContains(
|
||
response,
|
||
('<a href="" class="btn btn-sm btn-mini btn-primary js-add" '
|
||
f'data-url="{add_url}" role="button" title="Ajouter un intervenant">+</a>'),
|
||
html=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
('<a href="" class="btn btn-sm btn-mini js-edit"'
|
||
f'data-url="{edit_url}" role="button" title="Modifier une intervention">'
|
||
'<img src="/static/admin/img/icon-changelink.svg"></a>'),
|
||
html=True
|
||
)
|
||
response = self.client.post(
|
||
reverse('intervenant-edit', args=[famille.pk, intervention.pk]), data={
|
||
'intervenant': intervenant.pk, 'role': role.pk,
|
||
'date_debut': date_debut, 'date_fin': date.today()
|
||
}
|
||
)
|
||
self.assertRedirects(response, reverse('famille-suivi', args=[famille.pk]))
|
||
intervention.refresh_from_db()
|
||
self.assertEqual(intervention.date_fin, date.today())
|
||
|
||
def test_document_upload_delete(self):
|
||
famille = Famille.objects.first()
|
||
with open(__file__, mode='rb') as fh:
|
||
response = self.client.post(reverse('famille-doc-upload', args=[famille.pk]), data={
|
||
'famille': famille.pk,
|
||
'fichier': File(fh),
|
||
'titre': 'Titre1',
|
||
})
|
||
self.assertRedirects(response, famille.suivi_url)
|
||
self.assertEqual(famille.documents.count(), 1)
|
||
os.remove(famille.documents.first().fichier.path)
|
||
# Adding second file with same title gives a validation error
|
||
with open(__file__, mode='rb') as fh:
|
||
response = self.client.post(reverse('famille-doc-upload', args=[famille.pk]), data={
|
||
'famille': famille.pk,
|
||
'fichier': File(fh),
|
||
'titre': 'Titre1',
|
||
})
|
||
self.assertEqual(
|
||
response.context['form'].errors['__all__'],
|
||
['Un objet Document avec ces champs Famille et Titre existe déjà.']
|
||
)
|
||
# Delete
|
||
response = self.client.post(
|
||
reverse('famille-doc-delete', args=[famille.pk, famille.documents.first().pk])
|
||
)
|
||
self.assertRedirects(response, famille.suivi_url)
|
||
|
||
def test_ajout_rapport(self):
|
||
famille = Famille.objects.first()
|
||
other_user = Utilisateur.objects.create_user(
|
||
'other', 'other@example.org', 'mepassword', prenom='Bruce', nom='Externe',
|
||
)
|
||
other_user.groups.add(Group.objects.get(name='aemo'))
|
||
famille.suivi.intervenants.add(other_user, through_defaults={'role': Role.objects.get(nom='Psy')})
|
||
famille.suivi.intervenants.add(self.user_aemo, through_defaults={
|
||
'role': Role.objects.get(nom='Psy'), 'date_fin': date.today() - timedelta(days=3)
|
||
})
|
||
response = self.client.get(reverse('famille-rapport-add', args=[famille.pk]))
|
||
# Seule l'intervention active est visible
|
||
self.assertQuerySetEqual(response.context['form']['sig_interv'].field.queryset, [other_user])
|
||
|
||
rapport_data = {
|
||
'date': date.today(),
|
||
'situation': '<p>Assez bonne</p>',
|
||
'evolutions': '<p>1<br>2<br>3</p>',
|
||
'evaluation': '<p>Ha!</p>',
|
||
'projet': '<p>Bon</p>',
|
||
}
|
||
response = self.client.post(
|
||
reverse('famille-rapport-add', args=[famille.pk]), data=rapport_data
|
||
)
|
||
self.assertRedirects(response, reverse('famille-agenda', args=[famille.pk]))
|
||
rapport = famille.rapports.first()
|
||
self.assertTrue(rapport.can_edit(self.user_aemo))
|
||
self.assertTrue(rapport.can_edit(other_user))
|
||
# Test édition
|
||
rapport_data.update({'date': date.today(), 'projet': '<p>Un autre</p>'})
|
||
response = self.client.post(
|
||
reverse('famille-rapport-edit', args=[famille.pk, rapport.pk]), data=rapport_data
|
||
)
|
||
if response.status_code == 200:
|
||
self.fail(response.context['form'].errors)
|
||
rapport.refresh_from_db()
|
||
self.assertEqual(rapport.date, date.today())
|
||
# Test vue/impression
|
||
response = self.client.get(reverse('famille-rapport-view', args=[famille.pk, rapport.pk]))
|
||
self.assertContains(response, "<p>Assez bonne</p>")
|
||
response = self.client.get(reverse('famille-rapport-print', args=[famille.pk, rapport.pk]))
|
||
self.assertEqual(response['content-type'], 'application/pdf')
|
||
|
||
def test_suppression_rapport(self):
|
||
famille = Famille.objects.first()
|
||
rapp = Rapport.objects.create(
|
||
famille=famille, date=date(2020, 4, 18), auteur=self.user_aemo, situation="La situation"
|
||
)
|
||
response = self.client.post(reverse('famille-rapport-delete', args=[famille.pk, rapp.pk]))
|
||
self.assertRedirects(response, reverse('famille-agenda', args=[famille.pk]))
|
||
|
||
def test_ajoute_contact_a_enfant_suivi(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
new_contact = Contact.objects.get(nom='DrSpontz')
|
||
add_contact_url = reverse('personne-reseau-add', args=[pers.pk])
|
||
response = self.client.post(add_contact_url, data={'contacts[]': new_contact.pk})
|
||
self.assertEqual(response.json(), {'is_valid': True})
|
||
self.assertEqual(pers.reseaux.count(), 1)
|
||
|
||
def test_creation_contact_possible_pour_educ(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
educ = Utilisateur.objects.create_user(
|
||
'other', 'other@example.org', 'mepassword', prenom='Bruce', nom='Externe',
|
||
)
|
||
educ.groups.add(Group.objects.get(name='aemo'))
|
||
self.client.force_login(self.user_aemo)
|
||
add_contact_url = f"{reverse('contact-add')}?forpers={pers.pk}"
|
||
new_contact = {
|
||
'nom': "ContactNom",
|
||
'prenom': 'ContactPrenom'
|
||
}
|
||
response = self.client.post(add_contact_url, data=new_contact)
|
||
self.assertTrue(response.status_code, 200)
|
||
response = self.client.get(reverse('personne-reseau-list', args=[pers.pk]))
|
||
self.assertContains(response, "<td>ContactNom ContactPrenom</td>", html=True)
|
||
self.assertEqual(pers.reseaux.count(), 1)
|
||
|
||
def test_retirer_contact_du_reseau(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
pers = Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
new_contact = Contact.objects.get(nom='DrSpontz')
|
||
pers.reseaux.add(new_contact)
|
||
self.assertEqual(pers.reseaux.count(), 1)
|
||
|
||
remove_url = reverse('personne-reseau-remove', args=[pers.pk, new_contact.pk])
|
||
response = self.client.post(remove_url, data={})
|
||
self.assertTrue(response.status_code, 302)
|
||
pers.refresh_from_db()
|
||
self.assertEqual(pers.reseaux.count(), 0)
|
||
|
||
def test_suivis_en_cours(self):
|
||
dates = [
|
||
# date_demande, date_debut_eval, date_debut_suivi, suivi en cours entre 1-28.2 ?
|
||
(None, None, None, False),
|
||
(date(2020, 2, 15), None, None, True),
|
||
(None, date(2020, 2, 15), None, True),
|
||
(None, None, date(2020, 2, 15), True),
|
||
(None, None, date(2020, 3, 3), False),
|
||
]
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
for date_demande, date_debut_evaluation, date_debut_suivi, en_cours in dates:
|
||
famille.suivi.date_demande = date_demande
|
||
famille.suivi.date_debut_evaluation = date_debut_evaluation
|
||
famille.suivi.date_debut_suivi = date_debut_suivi
|
||
famille.suivi.save()
|
||
familles = Famille.suivis_en_cours(date(2020, 2, 1), date(2020, 2, 28))
|
||
if en_cours:
|
||
self.assertIn(famille, familles)
|
||
else:
|
||
self.assertNotIn(famille, familles)
|
||
|
||
|
||
class SuiviTests(InitialDataMixin, TestCase):
|
||
def setUp(self):
|
||
super().setUp()
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
def test_suivi_dossier(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
suivi_url = reverse('famille-suivi', args=[famille.pk])
|
||
response = self.client.get(suivi_url)
|
||
self.assertContains(
|
||
response,
|
||
'<button class="btn btn-sm btn-success" name="save" type="submit">Enregistrer</button>',
|
||
html=True
|
||
)
|
||
response = self.client.post(suivi_url, data={
|
||
'equipe': 'montagnes',
|
||
'ope_referent': Contact.objects.get(nom='Rathfeld').pk,
|
||
'date_demande': '2018-10-24',
|
||
'etape_suivi': 'demande',
|
||
})
|
||
self.assertRedirects(response, suivi_url)
|
||
suivi = famille.suivi
|
||
self.assertEqual(suivi.equipe, 'montagnes')
|
||
|
||
def test_suivi_lecture_seule(self):
|
||
user_other = Utilisateur.objects.create_user(
|
||
'user_other', 'user_other@example.org', nom='Aemo2', prenom='Prénom', sigle='SP2'
|
||
)
|
||
user_other.groups.add(Group.objects.get(name='aemo'))
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
famille.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')}
|
||
)
|
||
self.client.force_login(user_other)
|
||
suivi_url = reverse('famille-suivi', args=[famille.pk])
|
||
response = self.client.get(suivi_url + '?confirm=1')
|
||
self.assertFalse(response.context['can_edit'])
|
||
self.assertNotContains(response, 'Enregistrer')
|
||
|
||
def test_permission_effacement_definitif_saisie_par_erreur(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes'
|
||
)
|
||
famille.suivi.date_fin_suivi = date.today() - timedelta(days=500)
|
||
famille.suivi.save()
|
||
self.assertFalse(famille.can_be_deleted(self.user_aemo))
|
||
|
||
self.user_aemo.user_permissions.add(Permission.objects.get(codename='change_famille'))
|
||
self.user_aemo.user_permissions.add(Permission.objects.get(codename='can_archive'))
|
||
# Recharger pour réinitialiser cache des permissions
|
||
user_mont = Utilisateur.objects.get(pk=self.user_aemo.pk)
|
||
self.client.force_login(user_mont)
|
||
self.assertTrue(famille.can_be_archived(user_mont))
|
||
|
||
famille.suivi.date_fin_suivi = None
|
||
famille.suivi.save()
|
||
response = self.client.post(
|
||
reverse('famille-agenda', args=[famille.pk]),
|
||
data={'date_demande': date.today(),
|
||
'date_debut_evaluation': date.today(),
|
||
'date_fin_evaluation': date.today(),
|
||
'motif_fin_suivi': 'erreur'}
|
||
)
|
||
# Lorsque le dossier est fermé, la redirection se fait sur la liste des familles
|
||
self.assertRedirects(response, reverse('famille-list'))
|
||
|
||
famille.refresh_from_db()
|
||
self.assertEqual(famille.suivi.date_fin_suivi, date.today())
|
||
self.assertEqual(famille.suivi.motif_fin_suivi, 'erreur')
|
||
self.assertTrue(famille.can_be_deleted(user_mont))
|
||
|
||
def test_date_suivante_bilan(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes'
|
||
)
|
||
famille.suivi.date_debut_suivi = date.today() - timedelta(days=90)
|
||
famille.suivi.save()
|
||
self.assertEqual(famille.suivi.etape.code, 'debut_suivi')
|
||
self.assertEqual(famille.suivi.date_suivante(), date.today())
|
||
Bilan.objects.create(
|
||
date=date.today() - timedelta(days=5),
|
||
auteur=self.user_aemo,
|
||
famille=famille,
|
||
)
|
||
self.assertEqual(famille.suivi.date_suivante(), date.today() + timedelta(days=90 - 5))
|
||
|
||
def test_date_fin_suivi_prevue(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes'
|
||
)
|
||
famille.suivi.date_debut_suivi = date.today() - timedelta(days=90)
|
||
famille.suivi.save()
|
||
Niveau.objects.create(
|
||
famille=famille, niveau_interv=2, date_debut=famille.suivi.date_debut_suivi
|
||
)
|
||
self.assertEqual(
|
||
Suivi.WORKFLOW['fin_suivi'].delai_depuis(famille.suivi),
|
||
famille.suivi.date_debut_suivi + timedelta(days=EtapeFin.delai_standard)
|
||
)
|
||
Niveau.objects.create(
|
||
famille=famille, niveau_interv=3, date_debut=date.today() - timedelta(days=5)
|
||
)
|
||
famille = Famille.objects.get(pk=famille.pk)
|
||
self.assertEqual(famille.niveau_actuel(), 3)
|
||
self.assertEqual(
|
||
Suivi.WORKFLOW['fin_suivi'].delai_depuis(famille.suivi),
|
||
date.today() - timedelta(days=5) + timedelta(days=EtapeFin.delai_niveau3)
|
||
)
|
||
|
||
def test_bilan_form(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Simpson', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes'
|
||
)
|
||
famille.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')}
|
||
)
|
||
famille.suivi.intervenants.add(
|
||
self.user_aemo2, through_defaults={
|
||
'role': Role.objects.get(nom='Educ'), 'date_fin': date.today() - timedelta(days=3)
|
||
}
|
||
)
|
||
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(reverse('famille-bilan-add', args=[famille.pk]))
|
||
# Seule l'intervention active est visible
|
||
self.assertQuerySetEqual(response.context['form']['sig_interv'].field.queryset, [self.user_aemo])
|
||
|
||
response = self.client.post(reverse('famille-bilan-add', args=[famille.pk]), data={
|
||
'date': '2020-08-30',
|
||
'objectifs': '<p class="msoNormal"><span>Objectifs</span></p>',
|
||
'rythme': '<p class="msoNormal"><span>Rythme</span></p>',
|
||
})
|
||
self.assertRedirects(response, reverse('famille-agenda', args=[famille.pk]))
|
||
bilan = famille.bilans.first()
|
||
self.assertEqual(bilan.objectifs, '<p>Objectifs</p>')
|
||
self.assertEqual(bilan.rythme, '<p>Rythme</p>')
|
||
|
||
|
||
class AgendaTests(InitialDataMixin, TestCase):
|
||
def setUp(self):
|
||
super().setUp()
|
||
self.client.force_login(self.user_aemo)
|
||
self.request = RequestFactory().get('/')
|
||
self.request.user = self.user_aemo
|
||
|
||
def test_affichage_agenda(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
self.client.force_login(self.user_aemo)
|
||
suivi_url = reverse('famille-agenda', args=[famille.pk])
|
||
response = self.client.get(suivi_url)
|
||
self.assertContains(
|
||
response,
|
||
'<input type="text" name="date_demande" value="{}" '
|
||
'class="vDateField vDateField-rounded" size="10" id="id_date_demande">'.format(format_d_m_Y(date.today())),
|
||
html=True
|
||
)
|
||
|
||
def test_dates_obligatoires(self):
|
||
today = date.today()
|
||
form_data = {
|
||
field_name: today for field_name in AgendaForm._meta.fields
|
||
if field_name not in ['date_fin_suivi', 'motif_fin_suivi', 'destination']
|
||
}
|
||
for field, etape in Suivi.WORKFLOW.items():
|
||
data2 = dict(form_data)
|
||
if etape.oblig is True:
|
||
etape_preced_oblig = Suivi.WORKFLOW[etape.preced_oblig]
|
||
data2[etape_preced_oblig.date_nom()] = ''
|
||
if etape.code == 'fin_suivi':
|
||
data2['date_fin_suivi'] = today
|
||
data2['motif_fin_suivi'] = 'placement'
|
||
data2['destination'] = 'fah'
|
||
form = AgendaForm(data2, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(form.errors, {'__all__': ['La date «{}» est obligatoire'.format(etape_preced_oblig)]})
|
||
else:
|
||
form = AgendaForm(data2, request=self.request)
|
||
self.assertTrue(form.is_valid())
|
||
|
||
def test_fin_suivi(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Loiseau', rue='Château1', npa=2000, localite='Moulinsart', equipe='montagnes',
|
||
)
|
||
today = date.today()
|
||
suivi = famille.suivi
|
||
form_data = {}
|
||
suivi.date_demande = form_data['date_demande'] = today - timedelta(days=360)
|
||
suivi.date_debut_evaluation = form_data['date_debut_evaluation'] = today - timedelta(days=290)
|
||
suivi.date_fin_evaluation = form_data['date_fin_evaluation'] = today - timedelta(days=250)
|
||
suivi.date_debut_suivi = form_data['date_debut_suivi'] = today - timedelta(days=120)
|
||
suivi.save()
|
||
form = AgendaForm(
|
||
data={**form_data, 'date_fin_suivi': today - timedelta(days=5),
|
||
'motif_fin_suivi': 'evol_positive', 'destination': 'fah'},
|
||
instance=suivi,
|
||
request=self.request,
|
||
)
|
||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||
suivi = form.save()
|
||
self.assertEqual(suivi.date_fin_suivi, today - timedelta(days=5))
|
||
|
||
def test_motif_fin_suivi_sans_date(self):
|
||
data = {'date_demande': date.today(),
|
||
'date_debut_evaluation': date.today(),
|
||
'date_fin_evaluation': date.today(),
|
||
'date_debut_suivi': date.today(),
|
||
'motif_fin_suivi': 'evol_positive'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'__all__': ["Les champs «Fin de l'accompagnement», «Motif de fin» et «Destination» "
|
||
"sont obligatoires pour fermer le dossier."]}
|
||
)
|
||
# Test avec date_fin_suivi non valide
|
||
data['date_fin_suivi'] = '2019-01-32'
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'date_fin_suivi': ['Saisissez une date valide.'],
|
||
'__all__': ["Les champs «Fin de l'accompagnement», «Motif de fin» et «Destination» "
|
||
"sont obligatoires pour fermer le dossier."]
|
||
}
|
||
)
|
||
|
||
def test_dates_non_chronologiques(self):
|
||
data = {
|
||
field_name: '2019-01-15' for field_name in AgendaForm._meta.fields
|
||
if field_name not in ['date_fin_suivi', 'motif_fin_suivi', 'destination']
|
||
}
|
||
date_field_preced = None
|
||
for field_name in AgendaForm._meta.fields:
|
||
if field_name in ['date_demande', 'motif_fin_suivi', 'destination']:
|
||
date_field_preced = field_name
|
||
continue
|
||
elif field_name == 'date_fin_suivi':
|
||
data = dict(
|
||
data, date_fin_suivi='2019-01-15', motif_fin_suivi='placement', destination='famille'
|
||
)
|
||
form = AgendaForm(dict(data, **{date_field_preced: '2019-01-16'}), request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'__all__':
|
||
["La date «{}» ne respecte pas l’ordre chronologique!".format(form.fields[field_name].label)]}
|
||
)
|
||
date_field_preced = field_name
|
||
# Test avec trou dans les valeurs de dates
|
||
data = {
|
||
'date_demande': '2019-01-15',
|
||
'date_fin_evaluation': '2019-01-01', # Ordre chronologique non respecté
|
||
'date_debut_suivi': '2019-02-01'
|
||
}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'__all__': ["La date «Fin de l’évaluation le» ne respecte pas l’ordre chronologique!"]}
|
||
)
|
||
|
||
def test_saisie_date_invalide(self):
|
||
form = AgendaForm({
|
||
'date_demande': '20.8',
|
||
}, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(form.errors, {'date_demande': ['Saisissez une date valide.']})
|
||
|
||
def test_saisie_par_erreur_OK(self):
|
||
data = {'motif_fin_suivi': 'erreur'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertTrue(form.is_valid())
|
||
self.assertEqual(form.cleaned_data['date_fin_suivi'], date.today())
|
||
|
||
def test_demande_non_aboutie(self):
|
||
data = {'motif_fin_suivi': 'non_aboutie'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertTrue(form.is_valid())
|
||
self.assertEqual(form.cleaned_data['date_fin_suivi'], date.today())
|
||
|
||
def test_abandon_durant_evaluation_1(self):
|
||
data = {'date_demande': date.today(), 'motif_fin_suivi': 'placement',
|
||
'destination': 'famille'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertTrue(form.is_valid(), form.errors)
|
||
|
||
def test_abandon_durant_evaluation_2(self):
|
||
data = {'date_demande': date.today(), 'motif_fin_suivi': 'placement', 'destination': 'famille'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertTrue(form.is_valid())
|
||
|
||
def test_dates_tardives(self):
|
||
date_passee = date.today() - timedelta(days=31 + Prestation.DELAI_SAISIE_SUPPL)
|
||
form_data = {}
|
||
suivi = Suivi()
|
||
for date_field in AgendaForm._meta.fields:
|
||
if not date_field.startswith('date'):
|
||
continue
|
||
if date_field == 'date_fin_suivi':
|
||
form_data['motif_fin_suivi'] = 'placement'
|
||
form_data['destination'] = 'famille'
|
||
form_data[date_field] = date_passee
|
||
form = AgendaForm(data=form_data, instance=suivi, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
if date_field == 'date_fin_suivi':
|
||
self.assertEqual(
|
||
form.errors,
|
||
{date_field: ["La saisie de dates pour le mois précédent n’est pas permise !"],
|
||
'__all__': ["Les champs «Fin de l'accompagnement», «Motif de fin» et «Destination» "
|
||
"sont obligatoires pour fermer le dossier."]}
|
||
)
|
||
else:
|
||
self.assertEqual(
|
||
form.errors,
|
||
{date_field: ["La saisie de dates pour le mois précédent n’est pas permise !"]}
|
||
)
|
||
setattr(suivi, date_field, date.today() - timedelta(days=90))
|
||
form_data[date_field] = date.today() - timedelta(days=90)
|
||
|
||
def test_date_demande_anticipee(self):
|
||
date_demande = date.today() + timedelta(days=1)
|
||
data = {'date_demande': date_demande}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'date_demande': ["La saisie anticipée est impossible !"]}
|
||
)
|
||
|
||
def test_sans_destination_erreur(self):
|
||
data = {'date_demande': date.today(),
|
||
'date_debut_evaluation': date.today(),
|
||
'date_fin_evaluation': date.today(),
|
||
'date_debut_suivi': date.today(),
|
||
'date_fin_suivi': date.today(),
|
||
'motif_fin_suivi': 'evol_positive'}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'__all__': ["Les champs «Fin de l'accompagnement», «Motif de fin» et «Destination» "
|
||
"sont obligatoires pour fermer le dossier."]}
|
||
)
|
||
|
||
data['destination'] = ''
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'__all__': ["Les champs «Fin de l'accompagnement», «Motif de fin» et «Destination» "
|
||
"sont obligatoires pour fermer le dossier."]}
|
||
)
|
||
|
||
def test_date_debut_suivi_anticipe_ok(self):
|
||
data = {'date_demande': date.today(),
|
||
'date_debut_evaluation': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI),
|
||
'date_fin_evaluation': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI),
|
||
'date_debut_suivi': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI)}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertTrue(form.is_valid())
|
||
|
||
def test_date_debut_suivi_anticipe_error(self):
|
||
data = {'date_demande': date.today(),
|
||
'date_debut_evaluation': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI + 1),
|
||
'date_fin_evaluation': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI + 1),
|
||
'date_debut_suivi': date.today() + timedelta(days=ANTICIPATION_POUR_DEBUT_SUIVI + 1)}
|
||
form = AgendaForm(data, request=self.request)
|
||
self.assertFalse(form.is_valid())
|
||
|
||
def test_date_anticipee_pour_groupe_admin(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(
|
||
reverse('famille-agenda', args=[famille.pk]),
|
||
data={'date_demande': '2022-09-01'},
|
||
follow=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<li class="alert alert-warning">Les dates saisies peuvent affecter les statistiques '
|
||
'déjà communiquées !</li>',
|
||
html=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<li class="alert alert-success">Les modifications ont été enregistrées avec succès</li>',
|
||
html=True
|
||
)
|
||
|
||
def test_affichage_intervention_temporaire(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
intervenant = self.user_aemo
|
||
role = Role.objects.get(nom='Educ')
|
||
date_debut = date.today()
|
||
intervention = Intervenant.objects.create(
|
||
suivi=famille.suivi, intervenant=intervenant, role=role, date_debut=date_debut, date_fin=date.today()
|
||
)
|
||
self.client.force_login(self.user_aemo)
|
||
suivi_url = reverse('famille-agenda', args=[famille.pk])
|
||
response = self.client.get(suivi_url)
|
||
self.assertContains(
|
||
response,
|
||
(
|
||
f"<div>Aemo Prénom (Educ) ({format_d_m_Y(intervention.date_debut)} - "
|
||
f"{format_d_m_Y(intervention.date_fin)})</div>"
|
||
),
|
||
html=True
|
||
)
|
||
|
||
|
||
class JournalisationTests(InitialDataMixin, TestCase):
|
||
def test_acces_famille_journalise(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
Intervenant.objects.create(
|
||
suivi=famille.suivi, intervenant=self.user_aemo,
|
||
role=Role.objects.get(nom='Educ'),
|
||
date_debut=date.today(),
|
||
)
|
||
Intervenant.objects.create(
|
||
suivi=famille.suivi, intervenant=self.user_aemo2,
|
||
role=Role.objects.get(nom='Educ'),
|
||
date_debut=date.today() - timedelta(days=3),
|
||
date_fin=date.today() - timedelta(days=1),
|
||
)
|
||
self.client.force_login(self.user_aemo)
|
||
suivi_url = reverse('famille-suivi', args=[famille.pk])
|
||
response = self.client.get(suivi_url)
|
||
self.assertTemplateUsed(response, 'aemo/suivi_edit.html')
|
||
|
||
self.client.force_login(self.user_aemo2)
|
||
response = self.client.get(suivi_url)
|
||
self.assertTemplateUsed(response, 'aemo/acces_famille.html')
|
||
response = self.client.get(suivi_url + '?confirm=1')
|
||
self.assertTemplateUsed(response, 'aemo/suivi_edit.html')
|
||
line = JournalAcces.objects.get(utilisateur=self.user_aemo)
|
||
self.assertTrue(line.ordinaire)
|
||
line = JournalAcces.objects.get(utilisateur=self.user_aemo2)
|
||
self.assertFalse(line.ordinaire)
|
||
|
||
|
||
@tag('pdf')
|
||
class PdfTests(InitialDataMixin, TestCase):
|
||
def setUp(self):
|
||
super().setUp()
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
def _test_print_pdf(self, url, filename):
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(url)
|
||
self.assertEqual(
|
||
response['content-disposition'],
|
||
'attachment; filename="{}"'.format(filename)
|
||
)
|
||
self.assertEqual(response['content-type'], 'application/pdf')
|
||
self.assertGreater(len(response.getvalue()), 200)
|
||
|
||
def test_print_evaluation(self):
|
||
fam = Famille.objects.get(nom='Haddock')
|
||
self._test_print_pdf(
|
||
reverse('print-evaluation', args=(fam.pk,)),
|
||
'haddock_aemo_evaluation.pdf'
|
||
)
|
||
# Avec genogramme en PDF
|
||
with (Path('.').parent / 'aemo' / 'test.pdf').open(mode='rb') as fh:
|
||
fam.genogramme = File(fh)
|
||
fam.save()
|
||
self._test_print_pdf(
|
||
reverse('print-evaluation', args=(fam.pk,)),
|
||
'haddock_aemo_evaluation.pdf'
|
||
)
|
||
|
||
def test_print_bilan(self):
|
||
fam = Famille.objects.get(nom='Haddock')
|
||
bilan = Bilan.objects.create(
|
||
date=date(2020, 11, 3),
|
||
auteur=self.user_aemo,
|
||
famille=fam,
|
||
objectifs="<p>Para 1<br><br>Para 2</p>",
|
||
rythme="<p>Para 1<br><br>Para 2</p>",
|
||
)
|
||
self._test_print_pdf(
|
||
reverse('print-bilan', args=(bilan.pk,)),
|
||
'haddock_bilan_20201103.pdf'
|
||
)
|
||
|
||
def test_print_coord_famille_un_enfant_un_parent(self):
|
||
fam = Famille.objects.get(nom='Haddock')
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
self._test_print_pdf(
|
||
reverse('print-coord-famille', args=(fam.pk,)),
|
||
'haddock_coordonnees.pdf'
|
||
)
|
||
|
||
def test_print_coord_un_enfant_deux_parents(self):
|
||
fam = Famille.objects.get(nom='Haddock')
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Maude', nom='Zarella',
|
||
role=Role.objects.get(nom='Mère')
|
||
)
|
||
self._test_print_pdf(
|
||
reverse('print-coord-famille', args=(fam.pk,)),
|
||
'haddock_coordonnees.pdf'
|
||
)
|
||
|
||
def test_print_coord_pere_mere_beaupere(self):
|
||
fam = Famille.objects.get(nom='Haddock')
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Maude', nom='Zarella',
|
||
role=Role.objects.get(nom='Mère')
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=fam, prenom='Aloïs', nom='Silalune',
|
||
role=Role.objects.get(nom='Beau-père')
|
||
)
|
||
self._test_print_pdf(
|
||
reverse('print-coord-famille', args=(fam.pk,)),
|
||
'haddock_coordonnees.pdf'
|
||
)
|
||
|
||
def test_print_sans_famille(self):
|
||
famille = Famille.objects.create_famille(
|
||
nom='Haddock', rue='Château1', npa=2000, localite='Moulinsart',
|
||
equipe='montagnes', autorite_parentale='conjointe', statut_marital='divorce',
|
||
monoparentale=False
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=famille, prenom='Gaston', nom='Lagaffe',
|
||
role=Role.objects.get(nom='Enfant suivi')
|
||
)
|
||
self._test_print_pdf(
|
||
reverse('print-coord-famille', args=(famille.pk,)),
|
||
'haddock_coordonnees.pdf'
|
||
)
|
||
|
||
|
||
class PrestationTests(InitialDataMixin, TestCase):
|
||
|
||
def setUp(self):
|
||
super().setUp()
|
||
self.famille = Famille.objects.get(nom='Haddock')
|
||
Personne.objects.create_personne(
|
||
famille=self.famille, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom='Haddock', prenom='Paulet', genre='M', date_naissance=date(1956, 2, 16),
|
||
rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
self.famille.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')}
|
||
)
|
||
self.prest_fam = LibellePrestation.objects.get(code='aemo01') # Évaluation
|
||
self.prest_gen = LibellePrestation.objects.get(code='aemo03')
|
||
|
||
def create_prestation_fam(self, texte=""):
|
||
prest = Prestation.objects.create(
|
||
auteur=self.user_aemo, date_prestation=date.today(), duree=timedelta(hours=8),
|
||
famille=self.famille, lib_prestation=self.prest_fam, texte=texte
|
||
)
|
||
prest.intervenants.add(self.user_aemo, self.user_aemo2)
|
||
return prest
|
||
|
||
def create_prestation_gen(self):
|
||
data = dict(
|
||
auteur=self.user_aemo, date_prestation=date.today(), duree=timedelta(hours=8),
|
||
famille=None, lib_prestation=self.prest_gen
|
||
)
|
||
prest = Prestation.objects.create(**data)
|
||
prest.intervenants.add(self.user_aemo)
|
||
return prest
|
||
|
||
def test_prestation_texte_clean(self):
|
||
"""Leading and trailing empty paragraphs are stripped."""
|
||
texte = (
|
||
'<p></p>\n'
|
||
'<p>Echanges mail fin de suivi, au revoir à la famille<br></p>\n'
|
||
'<p> </p>'
|
||
)
|
||
data = dict(
|
||
duree='3:40', date_prestation=date.today(), lib_prestation=self.prest_fam.pk,
|
||
intervenants=[self.user_aemo.pk], texte=texte
|
||
)
|
||
form = PrestationForm(famille=self.famille, user=self.user_aemo, data=data)
|
||
self.assertTrue(form.is_valid())
|
||
self.assertEqual(
|
||
form.cleaned_data['texte'],
|
||
'<p>Echanges mail fin de suivi, au revoir à la famille<br></p>'
|
||
)
|
||
|
||
def test_prestation_date_prestation_dans_mois_courant(self):
|
||
data = dict(
|
||
duree='3:40', date_prestation=date.today(), lib_prestation=self.prest_fam.pk,
|
||
intervenants=[self.user_aemo.pk]
|
||
)
|
||
form = PrestationForm(famille=self.famille, user=self.user_aemo, data=data)
|
||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||
|
||
def test_prestation_saisie_anticipee(self):
|
||
data = dict(
|
||
duree='3:40', date_prestation=date.today() + timedelta(days=1),
|
||
lib_prestation=self.prest_fam.pk, intervenants=[self.user_aemo.pk]
|
||
)
|
||
form = PrestationForm(famille=self.famille, user=self.user_aemo, data=data)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(form.errors, {'date_prestation': ['La saisie anticipée est impossible !']})
|
||
|
||
def test_prestation_saisie_tardive(self):
|
||
data = dict(
|
||
duree='3:40', date_prestation=date.today() - timedelta(days=31 + Prestation.DELAI_SAISIE_SUPPL),
|
||
lib_prestation=self.prest_fam.pk, intervenants=[self.user_aemo.pk]
|
||
)
|
||
form = PrestationForm(famille=self.famille, user=self.user_aemo, data=data)
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors,
|
||
{'date_prestation': ['La saisie des prestations des mois précédents est close !']}
|
||
)
|
||
|
||
def test_prestation_edit_perm_speciale(self):
|
||
prest = self.create_prestation_fam()
|
||
prest.date_prestation = date.today() - timedelta(days=31 + Prestation.DELAI_SAISIE_SUPPL)
|
||
prest.save()
|
||
self.user_admin.user_permissions.add(
|
||
Permission.objects.get(codename='edit_prest_prev_month', content_type__app_label='aemo')
|
||
)
|
||
self.client.force_login(self.user_admin)
|
||
self.client.post(reverse('prestation-edit', args=[self.famille.pk, prest.pk]), data={
|
||
'date_prestation': prest.date_prestation,
|
||
'duree': '00:45',
|
||
'intervenants': [self.user_aemo.pk],
|
||
'texte': 'foo',
|
||
})
|
||
prest.refresh_from_db()
|
||
self.assertEqual(prest.texte, 'foo')
|
||
|
||
def test_add_prestation_fam(self):
|
||
add_url = reverse('prestation-famille-add', args=[self.famille.pk])
|
||
data = dict(
|
||
duree='3:40', date_prestation=date.today() - timedelta(days=3), famille=self.famille.pk,
|
||
intervenants=[self.user_aemo.pk]
|
||
)
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.post(add_url, data)
|
||
if response.status_code == 200:
|
||
self.fail(response.context['form'].errors)
|
||
self.assertRedirects(response, reverse('journal-list', args=[self.famille.pk]))
|
||
prestation = self.famille.prestations.get(duree="3:40")
|
||
# Évaluation choisie auto car pas de date de début de suivi
|
||
self.assertEqual(prestation.lib_prestation.code, 'aemo01')
|
||
|
||
# Le type de prestation dépend de la date exacte de début de suivi.
|
||
self.famille.suivi.date_debut_suivi = date.today() - timedelta(days=1)
|
||
self.famille.suivi.save()
|
||
data.update({'date_prestation': date.today(), 'duree': '1:00'})
|
||
response = self.client.post(add_url, data)
|
||
prestation = self.famille.prestations.get(duree="1:00")
|
||
self.assertEqual(prestation.lib_prestation.code, 'aemo02')
|
||
data.update({'date_prestation': date.today() - timedelta(days=2), 'duree': '1:30'})
|
||
response = self.client.post(add_url, data)
|
||
prestation = self.famille.prestations.get(duree="1:30")
|
||
self.assertEqual(prestation.lib_prestation.code, 'aemo01')
|
||
|
||
def test_affichage_prestation_menu_fam(self):
|
||
self.create_prestation_fam()
|
||
menu_url = reverse('prestation-menu')
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(menu_url)
|
||
self.assertContains(
|
||
response,
|
||
'<td class="total">16:00</td>',
|
||
html=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<td class="mesprest">08:00</td>',
|
||
html=True
|
||
)
|
||
|
||
def test_add_prestation_gen(self):
|
||
add_url = reverse('prestation-gen-add')
|
||
data = dict(
|
||
duree='3:40', famille='',
|
||
date_prestation=date.today() - timedelta(days=360), # Too old!
|
||
intervenants=[self.user_aemo.pk]
|
||
)
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.post(add_url, data)
|
||
self.assertEqual(
|
||
response.context['form'].errors,
|
||
{'date_prestation': ['La saisie des prestations des mois précédents est close !']}
|
||
)
|
||
data['date_prestation'] = date.today()
|
||
response = self.client.post(add_url, data)
|
||
self.assertRedirects(response, reverse('prestation-gen-list'))
|
||
self.assertEqual(self.user_aemo.prestations.first().lib_prestation.code, 'aemo03')
|
||
|
||
def test_update_prestation_fam(self):
|
||
prest = self.create_prestation_fam()
|
||
url = reverse('prestation-edit', args=[self.famille.pk, prest.pk])
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(url)
|
||
self.assertEqual(response.status_code, 200)
|
||
data = model_to_dict(prest)
|
||
data['fichier'] = ''
|
||
data['intervenants'] = [str(interv.pk) for interv in data['intervenants']]
|
||
data['duree'] = '12:00'
|
||
response = self.client.post(url, data=data)
|
||
prest.refresh_from_db()
|
||
self.assertEqual(prest.duree, timedelta(hours=12))
|
||
|
||
def test_correction_prestation_debut_suivi_passe(self):
|
||
"""
|
||
Quand un début de suivi est saisi dans le passé, les prestations depuis
|
||
cette date sont passées en accompagnement.
|
||
"""
|
||
prest = self.create_prestation_fam()
|
||
self.assertEqual(prest.lib_prestation.code, 'aemo01')
|
||
self.assertIsNone(self.famille.suivi.date_debut_suivi)
|
||
self.famille.suivi.intervenants.add(
|
||
self.user_aemo, through_defaults={'role': Role.objects.get(nom='Educ')}
|
||
)
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.post(
|
||
reverse('famille-agenda', args=[self.famille.pk]),
|
||
data={
|
||
'date_demande': date.today() - timedelta(days=4),
|
||
'date_debut_evaluation': date.today() - timedelta(days=4),
|
||
'date_fin_evaluation': date.today() - timedelta(days=2),
|
||
'date_debut_suivi': date.today() - timedelta(days=2),
|
||
},
|
||
)
|
||
self.assertEqual(response.status_code, 302)
|
||
self.famille.refresh_from_db()
|
||
self.assertIsNotNone(self.famille.suivi.date_debut_suivi)
|
||
prest.refresh_from_db()
|
||
self.assertEqual(prest.lib_prestation.code, 'aemo02')
|
||
|
||
def test_droit_modification_prestation_familiale(self):
|
||
prest = Prestation.objects.create(
|
||
famille=self.famille,
|
||
auteur=self.user_admin,
|
||
lib_prestation=LibellePrestation.objects.get(code='aemo01'),
|
||
date_prestation=date.today(),
|
||
duree='1:10'
|
||
)
|
||
prest.intervenants.set([self.user_aemo])
|
||
|
||
self.client.force_login(self.user_aemo2)
|
||
with self.assertLogs('django.request', level='WARNING'):
|
||
response = self.client.get(reverse('prestation-edit', args=[self.famille.pk, prest.pk]))
|
||
self.assertEqual(response.status_code, 403)
|
||
self.assertTrue(prest.can_edit(self.user_aemo))
|
||
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('prestation-edit', args=[self.famille.pk, prest.pk]))
|
||
self.assertEqual(response.status_code, 200)
|
||
|
||
def test_affichage_prestation_personnelle(self):
|
||
self.create_prestation_fam()
|
||
self.create_prestation_gen()
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(reverse('prestation-personnelle'))
|
||
self.assertContains(
|
||
response,
|
||
'<tr><th>Total prestations aemo01</th><td align="right">08:00</td></tr>',
|
||
html=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<tr><th>Total prestations aemo03</th><td align="right">08:00</td></tr>',
|
||
html=True
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<tr class="border-top"><th>Total</th><th class ="text-end">16:00</th></tr>',
|
||
html=True
|
||
)
|
||
|
||
def test_affichage_prestation_generale(self):
|
||
self.create_prestation_fam()
|
||
self.create_prestation_gen()
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.get(reverse('prestation-generale'))
|
||
self.assertContains(
|
||
response,
|
||
'<td>08:00</td>',
|
||
html=True,
|
||
count=1
|
||
)
|
||
|
||
def test_suppression_prestation_famille(self):
|
||
prest_fam = self.create_prestation_fam()
|
||
self.client.force_login(self.user_aemo)
|
||
response = self.client.post(reverse('prestation-delete', args=[prest_fam.famille_id, prest_fam.pk]))
|
||
self.assertRedirects(response, reverse('journal-list', args=[prest_fam.famille_id]))
|
||
self.assertFalse(Prestation.objects.filter(pk=prest_fam.pk).exists())
|
||
|
||
def test_recherche_prestations(self):
|
||
texte1 = "La famille Lucky va bien"
|
||
texte2 = "En été, Luke tire bien plus vite que son ombre!"
|
||
prest1 = self.create_prestation_fam(texte1)
|
||
prest2 = self.create_prestation_fam(texte2)
|
||
self.client.force_login(self.user_aemo)
|
||
url = reverse('journal-list', args=[self.famille.pk])
|
||
|
||
# Note: les chaînes à rechercher sont en majuscule pour s'assurer que
|
||
# la recherche n'est pas sensible à la casse
|
||
|
||
# mot contenu dans les deux enregistrements
|
||
response = self.client.get(url, {"recherche": "BIEN"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest1, prest2])
|
||
|
||
# mot contenu dans le premier enregistrement
|
||
response = self.client.get(url, {"recherche": "FAMILLE"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest1])
|
||
|
||
# mot contenu dans le deuxième enregistrement
|
||
response = self.client.get(url, {"recherche": "OMBRE"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest2])
|
||
|
||
# mot contenu dans aucun enregistrement
|
||
response = self.client.get(url, {"recherche": "TINTIN"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [])
|
||
|
||
# deux mots contenus chacun dans un enregistrement différent
|
||
response = self.client.get(url, {"recherche": "FAMILLE OMBRE"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [])
|
||
|
||
# deux mots contenus dans le même enregistrement
|
||
response = self.client.get(url, {"recherche": "BIEN OMBRE"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest2])
|
||
|
||
# Recherche d'un mot avec accent (mot clé sans accent)
|
||
response = self.client.get(url, {"recherche": "ETE"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest2])
|
||
|
||
# Recherche d'un mot sans accent (mot clé avec accent)
|
||
response = self.client.get(url, {"recherche": "FÂMÌLLÉ"})
|
||
self.assertQuerySetEqual(response.context["object_list"], [prest1])
|
||
|
||
def test_message_recherche_prestations_sans_resultat(self):
|
||
pas_de_prestation = "Aucune prestation saisie"
|
||
recherche_vide = "Pas de résultat pour votre recherche."
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
# Message pour contenu vide sans recherche
|
||
response = self.client.get(reverse('journal-list', args=[self.famille.pk]))
|
||
self.assertContains(response, pas_de_prestation)
|
||
self.assertNotContains(response, recherche_vide)
|
||
|
||
# Message pour contenu vide lors d'une recherche
|
||
response = self.client.get(reverse('journal-list', args=[self.famille.pk]), {"recherche": "VIDE"})
|
||
self.assertContains(response, recherche_vide)
|
||
self.assertNotContains(response, pas_de_prestation)
|
||
|
||
|
||
class RapportTests(InitialDataMixin, TestCase):
|
||
|
||
@classmethod
|
||
def setUpTestData(cls):
|
||
super().setUpTestData()
|
||
cls.famille = Famille.objects.create_famille(nom='Doe')
|
||
cls.educ = Utilisateur.objects.create_user('Educ', 'educ@exemple.org', '123')
|
||
cls.educ.user_permissions.add(Permission.objects.get(codename='change_famille'))
|
||
|
||
def setUp(self) -> None:
|
||
self.create_kwargs = {
|
||
'famille': self.famille,
|
||
'auteur': self.educ,
|
||
'date': date.today(),
|
||
'situation': 'Situation initiale',
|
||
'observations': 'Observation'
|
||
}
|
||
|
||
def test_create_model(self):
|
||
rapport = Rapport.objects.create(**self.create_kwargs)
|
||
self.assertIsInstance(rapport, Rapport)
|
||
self.assertEqual(str(rapport), f"Résumé du {format_d_m_Y(date.today())} pour la famille Doe - ")
|
||
|
||
def test_create_view_with_observations(self):
|
||
self.client.force_login(self.educ)
|
||
response = self.client.get(reverse('famille-rapport-add', args=[self.famille.pk]))
|
||
self.assertContains(
|
||
response,
|
||
'<label for="id_observations">Observations, évolution et hypothèses :</label>',
|
||
html=True
|
||
)
|
||
self.assertNotIn('Évaluation / Hypothèses', response)
|
||
self.assertNotIn('Évolutions et observations', response)
|
||
|
||
def test_display_rapport_with_observations(self):
|
||
rapport = Rapport.objects.create(**self.create_kwargs)
|
||
self.client.force_login(self.educ)
|
||
response = self.client.get(reverse('famille-rapport-view', args=[self.famille.pk, rapport.pk]))
|
||
|
||
self.assertContains(response, '<h3>Observations, évolution et hypothèses</h3>', html=True)
|
||
|
||
|
||
class NiveauTests(InitialDataMixin, TestCase):
|
||
|
||
def setUp(self) -> None:
|
||
self.famille = Famille.objects.get(nom='Haddock')
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
def test_niveau_model(self):
|
||
niv = Niveau.objects.create(
|
||
famille=self.famille,
|
||
niveau_interv=2,
|
||
date_debut=date.today()
|
||
)
|
||
self.assertEqual(niv.famille, self.famille)
|
||
self.assertEqual(niv.niveau_interv, 2)
|
||
self.assertEqual(niv.date_debut, date.today())
|
||
self.assertEqual(niv.date_fin, None)
|
||
|
||
def test_niveau_add_view(self):
|
||
auj = date.today()
|
||
demain = auj + timedelta(days=1)
|
||
response = self.client.post(
|
||
path=reverse('niveau-add', args=[self.famille.pk]),
|
||
data={'niveau_interv': 3, 'date_debut': demain},
|
||
follow=True
|
||
)
|
||
self.assertContains(response, f"<td>{format_d_m_Y(demain)}</td><td>---</td><td>3</td>", html=True)
|
||
|
||
def test_niveau_add_form(self):
|
||
auj = date.today()
|
||
demain = auj + timedelta(days=1)
|
||
form = NiveauForm(famille=self.famille, data={'niveau_interv': 3, 'date_debut': demain})
|
||
self.assertTrue(form.is_valid())
|
||
|
||
def test_niveau_add_second_enregistrement(self):
|
||
auj = date.today()
|
||
demain = auj + timedelta(days=1)
|
||
niv = Niveau.objects.create(famille=self.famille, niveau_interv=2, date_debut=auj, date_fin=None)
|
||
self.client.post(
|
||
path=reverse('niveau-add', args=[self.famille.pk]),
|
||
data={'niveau_interv': 3, 'date_debut': demain},
|
||
follow=True
|
||
)
|
||
# Mise à jour dernier enreg.
|
||
niv.refresh_from_db()
|
||
self.assertEqual(niv.date_fin, auj)
|
||
|
||
# Test nouvel enreg.
|
||
self.assertEqual(self.famille.niveaux.count(), 2)
|
||
der_niv = self.famille.niveaux.last()
|
||
self.assertEqual(der_niv.famille, self.famille)
|
||
self.assertEqual(der_niv.niveau_interv, 3)
|
||
self.assertEqual(der_niv.date_debut, demain)
|
||
self.assertEqual(der_niv.date_fin, None)
|
||
|
||
def test_niveau_edit_view(self):
|
||
auj = date.today()
|
||
demain = auj + timedelta(days=1)
|
||
niv = Niveau.objects.create(famille=self.famille, niveau_interv=2, date_debut=auj, date_fin=None)
|
||
self.client.post(
|
||
path=reverse('niveau-edit', args=[self.famille.pk, niv.pk]),
|
||
data={'niveau_interv': 3, 'date_debut': demain},
|
||
follow=True
|
||
)
|
||
niv.refresh_from_db()
|
||
self.assertEqual(niv.niveau_interv, 3)
|
||
|
||
def test_niveau_edit_form(self):
|
||
auj = date.today()
|
||
demain = auj + timedelta(days=1)
|
||
niv = Niveau.objects.create(famille=self.famille, niveau_interv=2, date_debut=auj, date_fin=None)
|
||
form = NiveauForm(famille=self.famille, instance=niv, data={'niveau_interv': 3, 'date_debut': demain})
|
||
self.assertTrue(form.is_valid())
|
||
form.save()
|
||
niv.refresh_from_db()
|
||
self.assertEqual(niv.niveau_interv, 3)
|
||
|
||
def test_niveau_delete(self):
|
||
auj = date.today()
|
||
niv = Niveau.objects.create(famille=self.famille, niveau_interv=2, date_debut=auj, date_fin=None)
|
||
response = self.client.post(
|
||
path=reverse('niveau-delete', args=[self.famille.pk, niv.pk]),
|
||
follow=True
|
||
)
|
||
self.assertEqual(len(response.context['niveaux']), 0)
|
||
|
||
def test_niveau_affichage_dans_agenda(self):
|
||
auj = date.today()
|
||
Niveau.objects.create(
|
||
famille=self.famille, niveau_interv=2, date_debut=auj - timedelta(days=10), date_fin=None
|
||
)
|
||
agenda_url = reverse('famille-agenda', args=[self.famille.pk])
|
||
response = self.client.get(agenda_url)
|
||
self.assertContains(response, '<span class="fw-bold">Niv. d’intervention 2</span>', html=True)
|
||
# Fin niveau affiché au plus tard à fin du suivi.
|
||
self.famille.suivi.date_fin_suivi = auj
|
||
self.famille.suivi.save()
|
||
response = self.client.get(agenda_url)
|
||
self.assertEqual(response.context['niveaux'][0].date_fin_calc, auj)
|
||
|
||
def test_debut_suivi_selon_niveau(self):
|
||
"""Début du suivi peut varier selon changement de niveau 2/3."""
|
||
auj = date.today()
|
||
self.famille.suivi.date_debut_suivi = auj - timedelta(days=20)
|
||
self.famille.suivi.save()
|
||
Niveau.objects.create(
|
||
famille=self.famille, niveau_interv=2,
|
||
date_debut=auj - timedelta(days=20), date_fin=auj - timedelta(days=10)
|
||
)
|
||
Niveau.objects.create(
|
||
famille=self.famille, niveau_interv=3,
|
||
date_debut=auj - timedelta(days=10), date_fin=None
|
||
)
|
||
self.assertEqual(self.famille.suivi.debut_suivi_selon_niveau, auj - timedelta(days=10))
|
||
|
||
|
||
class UtilisateurTests(InitialDataMixin, TestCase):
|
||
|
||
def test_utilisateur_list(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('utilisateur-list'))
|
||
self.assertEqual(len(response.context['object_list']), Utilisateur.objects.count())
|
||
|
||
def test_create_utilisateur(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('utilisateur-add'), data={
|
||
'nom': 'Muller',
|
||
'prenom': 'Hans',
|
||
'username': 'MullerH',
|
||
'sigle': 'HM',
|
||
'groups': [Group.objects.create(name='grp1').pk, Group.objects.create(name='grp2').pk],
|
||
'taux_activite': 100,
|
||
'decharge': 2,
|
||
})
|
||
self.assertEqual(response.status_code, 302)
|
||
user = Utilisateur.objects.get(nom='Muller')
|
||
self.assertEqual(user.service.sigle, 'CRNE')
|
||
self.assertEqual(user.username, 'MullerH')
|
||
self.assertEqual(user.groups.count(), 2)
|
||
self.assertEqual(user.charge_max, 30)
|
||
|
||
def test_taux_activite(self):
|
||
data = {
|
||
'nom': 'Muller',
|
||
'prenom': 'Hans',
|
||
'username': 'MullerH',
|
||
'sigle': 'HM',
|
||
'taux_activite': 90,
|
||
}
|
||
form = UtilisateurForm(data=data)
|
||
self.assertTrue(form.is_valid())
|
||
|
||
form = UtilisateurForm(data={**data, 'taux_activite': 110})
|
||
self.assertFalse(form.is_valid())
|
||
self.assertEqual(
|
||
form.errors['taux_activite'],
|
||
['Assurez-vous que cette valeur est inférieure ou égale à 100.']
|
||
)
|
||
|
||
def test_delete_utilisateur(self):
|
||
user = Utilisateur.objects.create_user(username='user1', nom='Supprimer')
|
||
self.client.force_login(self.user_admin)
|
||
self.client.post(reverse('utilisateur-delete', args=[user.pk]))
|
||
user.refresh_from_db()
|
||
self.assertIsNotNone(user.date_desactivation)
|
||
self.assertFalse(user.is_active)
|
||
self.assertFalse(user.est_actif)
|
||
|
||
response = self.client.get(reverse('utilisateur-autocomplete') + '?q=Sup')
|
||
self.assertEqual(response.json()['results'], [])
|
||
|
||
@override_settings(PASSWORD_HASHERS=PASSWORD_HASHERS)
|
||
def test_reinit_password(self):
|
||
Utilisateur.objects.create_superuser(
|
||
'somebody', 'somebody@example.org', 'somebodypassword', prenom='Jean', nom='Valjean',
|
||
)
|
||
new_user = Utilisateur.objects.create_user(username='user')
|
||
self.assertTrue(new_user.password.startswith('!')) # Unusable password
|
||
self.client.login(username='somebody', password='somebodypassword')
|
||
self.client.post(reverse('utilisateur-password-reinit', args=[new_user.pk]))
|
||
new_user.refresh_from_db()
|
||
self.assertTrue(new_user.password.startswith('pbkdf2_sha256$')) # Usable password
|
||
|
||
def test_reinit_mobile(self):
|
||
from django_otp.plugins.otp_totp.models import TOTPDevice
|
||
user = Utilisateur.objects.create_user(username='user', nom="Spontz")
|
||
TOTPDevice.objects.create(user=user, name='default')
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('utilisateur-otp-device-reinit', args=[user.pk]), follow=True)
|
||
self.assertEqual(str(list(response.context['messages'])[0]), 'Le mobile de «Spontz » a été réinitialisé.')
|
||
response = self.client.post(reverse('utilisateur-otp-device-reinit', args=[user.pk]), follow=True)
|
||
self.assertEqual(
|
||
str(list(response.context['messages'])[0]),
|
||
'Aucune configuration mobile trouvée pour «Spontz »'
|
||
)
|
||
|
||
def test_liste_utilisateurs_actifs_inactifs(self):
|
||
user1 = Utilisateur.objects.create_user(
|
||
'User1P', 'user1@exemple.org', 'user1_password', prenom='Paul', nom='User1',
|
||
)
|
||
Utilisateur.objects.create_user(
|
||
'User2M', 'user2@exemple.org', 'user2_password', prenom='Max', nom='User2',
|
||
)
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('utilisateur-list'))
|
||
self.assertContains(response, 'User1 Paul')
|
||
self.assertContains(response, 'User2 Max')
|
||
self.client.post(reverse('utilisateur-delete', args=[user1.pk]))
|
||
response = self.client.get(reverse('utilisateur-list'))
|
||
self.assertNotContains(response, 'User1 Paul')
|
||
response = self.client.get(reverse('utilisateur-desactive-list'))
|
||
self.assertContains(response, 'User1 Paul')
|
||
|
||
def test_reactivation_utilisateur(self):
|
||
user1 = Utilisateur.objects.create_user(
|
||
'User1P', 'user1@exemple.org', 'user1_password', prenom='Paul', nom='User1',
|
||
)
|
||
Utilisateur.objects.create_user(
|
||
'User2M', 'user2@exemple.org', 'user2_password', prenom='Max', nom='User2',
|
||
)
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('utilisateur-delete', args=[user1.pk]), follow=True)
|
||
self.assertNotContains(response, 'User1 Paul')
|
||
user1.refresh_from_db()
|
||
self.assertIsNotNone(user1.date_desactivation)
|
||
response = self.client.post(reverse('utilisateur-reactiver', args=[user1.pk]), follow=True)
|
||
self.assertContains(response, 'User1 Paul')
|
||
user1.refresh_from_db()
|
||
self.assertIsNone(user1.date_desactivation)
|
||
|
||
|
||
class OtherTests(InitialDataMixin, TestCase):
|
||
def setUp(self):
|
||
self.client.force_login(self.user_aemo)
|
||
|
||
def test_contact_list(self):
|
||
response = self.client.get(reverse('contact-list'))
|
||
self.assertEqual(len(response.context['object_list']), 3)
|
||
response = self.client.get(reverse('contact-list') + '?service=%s' % Service.objects.get(sigle='OPEN').pk)
|
||
self.assertEqual(len(response.context['object_list']), 1)
|
||
response = self.client.get(reverse('contact-list') + '?role=%s' % Role.objects.get(nom='Médecin').pk)
|
||
self.assertEqual(len(response.context['object_list']), 1)
|
||
response = self.client.get(reverse('contact-list') + '?texte=barn')
|
||
self.assertEqual(len(response.context['object_list']), 1)
|
||
|
||
def test_contact_autocomplete(self):
|
||
medecin = Role.objects.get(nom='Médecin')
|
||
ope_service = Service.objects.create(sigle="OPEC")
|
||
other_service = Service.objects.get(sigle="SSE")
|
||
contact_ope = Contact.objects.create(
|
||
nom="Duplain", prenom="Irma", service=ope_service
|
||
)
|
||
contact_ope.roles.add(medecin)
|
||
contact_other = Contact.objects.create(
|
||
nom="Dupont", prenom="Paul", service=other_service
|
||
)
|
||
contact_other.roles.add(medecin)
|
||
response = self.client.get(reverse('contact-autocomplete') + '?q=Dup')
|
||
self.assertEqual(
|
||
[res['text'] for res in response.json()['results']],
|
||
['Duplain Irma (OPEC)', 'Dupont Paul (SSE)']
|
||
)
|
||
# The OPE version
|
||
response = self.client.get(reverse('contact-ope-autocomplete') + '?q=Dup')
|
||
self.assertEqual(
|
||
[res['text'] for res in response.json()['results']],
|
||
['Duplain Irma (OPEC)']
|
||
)
|
||
|
||
def test_supression_affichage_du_contact_desactive_dans_contact_autocomplete(self):
|
||
medecin = Role.objects.get(nom='Médecin')
|
||
ope_service = Service.objects.create(sigle="OPEC")
|
||
other_service = Service.objects.get(sigle="SSE")
|
||
contact_ope = Contact.objects.create(
|
||
nom="Duplain", prenom="Irma", service=ope_service, est_actif=False
|
||
)
|
||
contact_ope.roles.add(medecin)
|
||
contact_other = Contact.objects.create(
|
||
nom="Dupont", prenom="Paul", service=other_service
|
||
)
|
||
contact_other.roles.add(medecin)
|
||
response = self.client.get(reverse('contact-autocomplete') + '?q=Dup')
|
||
self.assertEqual(
|
||
[res['text'] for res in response.json()['results']],
|
||
['Dupont Paul (SSE)']
|
||
)
|
||
|
||
def test_suppression_affichage_contact_desactive_dans_list_contact(self):
|
||
medecin = Role.objects.get(nom='Médecin')
|
||
ope_service = Service.objects.create(sigle="OPEC")
|
||
other_service = Service.objects.get(sigle="SSE")
|
||
contact_ope = Contact.objects.create(
|
||
nom="Duplain", prenom="Irma", service=ope_service, est_actif=False
|
||
)
|
||
contact_ope.roles.add(medecin)
|
||
contact_other = Contact.objects.create(
|
||
nom="Dupont", prenom="Paul", service=other_service
|
||
)
|
||
contact_other.roles.add(medecin)
|
||
response = self.client.get(reverse('contact-list'))
|
||
self.assertNotContains(response, 'Duplain')
|
||
|
||
def test_controler_doublon_contact(self):
|
||
medecin = Role.objects.get(nom='Médecin')
|
||
contact1 = Contact.objects.create(
|
||
nom="Duplain", prenom="Irma", est_actif=True
|
||
)
|
||
contact1.roles.add(medecin)
|
||
doublon_url = reverse('contact-doublon')
|
||
response = self.client.post(doublon_url, data={'nom': "Duplain", 'prenom': "Irma"})
|
||
self.assertEqual(response.json(), [{'nom': "Duplain", 'prenom': "Irma"}])
|
||
response = self.client.post(doublon_url, data={'nom': "Nouveau", 'prenom': "Contact"})
|
||
# Réponse vide signifie pas de doublon détecté.
|
||
self.assertEqual(response.json(), '')
|
||
|
||
def test_service_creation(self):
|
||
s1 = Service.objects.create(sigle='lower') # transform code from lower to uppercase
|
||
self.assertEqual(s1.sigle, 'LOWER')
|
||
# By form
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(
|
||
reverse('service-add'), data={'sigle': 'SERVICE', 'nom_complet': 'Super service'}
|
||
)
|
||
self.assertRedirects(response, reverse('service-list'))
|
||
self.assertEqual(Service.objects.filter(sigle='SERVICE').count(), 1)
|
||
|
||
def test_service_list(self):
|
||
response = self.client.get(reverse('service-list'))
|
||
self.assertEqual(len(response.context['object_list']), 3)
|
||
|
||
def test_raise_unique_constraint_school_center_creation(self):
|
||
sc = CercleScolaire(nom='EOREN-MAIL')
|
||
self.assertRaises(IntegrityError, sc.save)
|
||
|
||
def test_cerclescolaire_list(self):
|
||
response = self.client.get(reverse('cercle-list'))
|
||
self.assertEqual(len(response.context['object_list']), 2)
|
||
|
||
def test_role_create(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('role-add'), data={'nom': 'ROLE1', 'famille': False})
|
||
self.assertRedirects(response, reverse('role-list'))
|
||
self.assertEqual(Role.objects.filter(nom='ROLE1').count(), 1)
|
||
|
||
def test_role_list(self):
|
||
response = self.client.get(reverse('role-list'))
|
||
self.assertGreater(len(response.context['object_list']), 10)
|
||
# Les rôles "protégés" ne sont pas éditables.
|
||
self.assertContains(response, '<td>Enfant suivi</td>')
|
||
|
||
def test_delete_used_role(self):
|
||
"""A role with at least one attached Personne cannot be deleted."""
|
||
role = Role.objects.get(nom="Père")
|
||
Personne.objects.create_personne(
|
||
famille=Famille.objects.create(nom='Schmurz'), role=role,
|
||
nom='Haddock', prenom='Archibald', genre='M', date_naissance=date(1956, 2, 16),
|
||
)
|
||
self.assertGreater(role.personne_set.count(), 0)
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('role-delete', args=[role.pk]), follow=True)
|
||
self.assertContains(response, "Cannot delete")
|
||
|
||
def test_truncate_with_more_ttag(self):
|
||
from aemo.templatetags.my_tags import truncate_html_with_more
|
||
txt = '<p>Ceci <b>est un très long</b> texte HTML.<br> Seconde ligne</p>'
|
||
self.assertHTMLEqual(
|
||
truncate_html_with_more(txt, 3),
|
||
'<div class="long hidden"><p>Ceci <b>est un très long</b> texte HTML.<br>'
|
||
' Seconde ligne</p></div>'
|
||
'<div class="short"><p>Ceci <b>est un…</b></p></div>'
|
||
'<a class="read_more" href=".">Afficher la suite</a>'
|
||
)
|
||
|
||
def test_info_ope_ttag(self):
|
||
from aemo.templatetags.my_tags import info_ope
|
||
self.assertEqual(
|
||
info_ope(Contact.objects.get(nom='Sybarnez')),
|
||
'<span title="032 886 88 88">Sybarnez Tina</span>'
|
||
)
|
||
|
||
def test_check_date_allowed(self):
|
||
with freeze_time("2021-01-20"):
|
||
self.assertFalse(Prestation.check_date_allowed(self.user_aemo, date(2020, 1, 20)))
|
||
with freeze_time("2021-01-04"):
|
||
self.assertFalse(Prestation.check_date_allowed(self.user_aemo, date(2020, 11, 30)))
|
||
self.assertTrue(Prestation.check_date_allowed(self.user_aemo, date(2020, 12, 2)))
|
||
self.assertTrue(Prestation.check_date_allowed(self.user_aemo, date(2021, 1, 2)))
|
||
|
||
with freeze_time("2020-11-02"):
|
||
self.assertFalse(Prestation.check_date_allowed(self.user_aemo, date(2019, 10, 15)))
|
||
self.assertTrue(Prestation.check_date_allowed(self.user_aemo, date(2020, 10, 15)))
|
||
self.assertTrue(Prestation.check_date_allowed(self.user_aemo, date(2020, 11, 12)))
|
||
|
||
def test_duration_field(self):
|
||
class SomeForm(Form):
|
||
duration = HMDurationField()
|
||
|
||
form = SomeForm({'duration': timedelta(days=1, hours=2, minutes=21, seconds=4)})
|
||
self.assertInHTML(
|
||
'<input type="text" name="duration" value="26:21" placeholder="hh:mm" required id="id_duration">',
|
||
form.as_div()
|
||
)
|
||
|
||
|
||
class TestExporter(ExportReporting):
|
||
"""A fake exporter class that just collect data in lists to be able to assert the contents."""
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.sheets = {}
|
||
self._current_sh = None
|
||
|
||
def __call__(self):
|
||
# This allows to provide an instance to mock
|
||
return self
|
||
|
||
def setup_sheet(self, title):
|
||
self.sheets[title] = []
|
||
self._current_sh = self.sheets[title]
|
||
|
||
def write_line(self, values, **kwargs):
|
||
self._current_sh.append(values)
|
||
|
||
|
||
class StatTests(TestCase):
|
||
@classmethod
|
||
def setUpTestData(cls):
|
||
group_aemo = Group.objects.create(name='aemo')
|
||
cls.user = Utilisateur.objects.create(
|
||
username='me', first_name='Jean', last_name='Valjean',
|
||
)
|
||
cls.user_admin = Utilisateur.objects.create(username='admin')
|
||
cls.user_admin.user_permissions.add(Permission.objects.get(codename='export_stats'))
|
||
user_haut = Utilisateur.objects.create(username='ld', prenom='Lise', nom="Duhaut")
|
||
user_haut.groups.add(group_aemo)
|
||
user_bas = Utilisateur.objects.create(username='jd', prenom='Jean', nom="Dubas")
|
||
user_bas.groups.add(group_aemo)
|
||
|
||
role_referent = Role.objects.create(nom='Référent', est_famille=False)
|
||
cls.enf_suivi = Role.objects.create(nom='Enfant suivi', est_famille=True)
|
||
cls.role_pere = Role.objects.create(nom='Père', est_famille=True)
|
||
cls.role_mere = Role.objects.create(nom='Mère', est_famille=True)
|
||
cls.famille_litt = Famille.objects.create_famille(
|
||
equipe='littoral',
|
||
nom='Haddock', rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=cls.famille_litt, role=cls.enf_suivi,
|
||
nom='Haddock', prenom='Archibald', genre='M', date_naissance=date(1996, 2, 16)
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=cls.famille_litt, role=cls.enf_suivi,
|
||
nom='Haddock', prenom='Honorine', genre='F', date_naissance=date(1999, 11, 2)
|
||
)
|
||
cls.famille_litt.suivi.date_demande = '2019-01-01'
|
||
cls.famille_litt.suivi.intervenants.add(user_bas, through_defaults={'role': role_referent})
|
||
cls.famille_litt.suivi.save()
|
||
|
||
cls.famille_mont = Famille.objects.create_famille(
|
||
equipe='montagnes',
|
||
nom='Tournesol', rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=cls.famille_mont, role=cls.enf_suivi,
|
||
nom='Tournesol', prenom='Tryphon', genre='M', date_naissance=date(1991, 1, 3)
|
||
)
|
||
cls.famille_mont.suivi.date_demande = '2019-01-01'
|
||
cls.famille_mont.suivi.intervenants.add(user_haut, through_defaults={'role': role_referent})
|
||
cls.famille_mont.suivi.save()
|
||
LibellePrestation.objects.bulk_create([
|
||
LibellePrestation(code='aemo01', nom='Évaluation AEMO'),
|
||
LibellePrestation( code='aemo04', nom='Activités ASE'),
|
||
])
|
||
|
||
def test_accueil_statistiques(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('stats'))
|
||
self.assertContains(response, 'Statistiques du 1<sup>er</sup>')
|
||
|
||
@freeze_time("2020-12-04")
|
||
def test_accueil_statistiques_decembre(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('stats'))
|
||
self.assertEqual(response.context['date_form'].data['end_month'], 1)
|
||
self.assertEqual(response.context['date_form'].data['end_year'], 2021)
|
||
|
||
def test_temps_total_prestations(self):
|
||
"""
|
||
Test Famille.temps_total_prestations()/temps_total_prestations_reparti(),
|
||
Test Utilisateur.temps_total_prestations()
|
||
"""
|
||
self.assertEqual(self.famille_litt.temps_total_prestations(), timedelta(0))
|
||
auj = date.today()
|
||
mois_sui1 = date(auj.year, auj.month, 3)
|
||
mois_sui2 = date(auj.year, auj.month, 4)
|
||
user2 = Utilisateur.objects.create(
|
||
username='you', first_name='Hans', last_name='Zwei',
|
||
)
|
||
user2.groups.add(Group.objects.get(name='aemo'))
|
||
p1 = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=auj,
|
||
duree='0:45'
|
||
)
|
||
p1.intervenants.set([self.user])
|
||
p2 = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=mois_sui1,
|
||
duree='1:0'
|
||
)
|
||
# Chaque intervenant saisit ses propres prestations
|
||
p2.intervenants.set([self.user])
|
||
p3 = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=mois_sui2,
|
||
duree='1:05'
|
||
)
|
||
p3.intervenants.set([user2])
|
||
|
||
# Avec ce processus, la même prestation peut avoir des durées différentes!!!
|
||
|
||
# p1 (00:45) + 2 interv. x p2 (1:00) >> p1(00:45) + p2(1:00) + p3(1:05) = 2:50
|
||
self.assertEqual(self.famille_litt.temps_total_prestations(), timedelta(hours=2, minutes=50))
|
||
self.assertEqual(self.famille_litt.temps_total_prestations_reparti(), timedelta(hours=1, minutes=25))
|
||
# self.user = p1 (00:45) + p2 (1:00) = 1:45
|
||
# user2 = p3(1:05)
|
||
self.assertEqual(format_duree(self.user.temps_total_prestations('aemo')), '01:45')
|
||
self.assertEqual(format_duree(user2.temps_total_prestations('aemo')), '01:05')
|
||
|
||
def test_stats(self):
|
||
auj = date.today()
|
||
mois_sui1 = date(auj.year, auj.month, 3)
|
||
user_bas = Utilisateur.objects.get(nom='Dubas')
|
||
p = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=auj,
|
||
duree='0:45'
|
||
)
|
||
p.intervenants.set([user_bas])
|
||
p = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=mois_sui1,
|
||
duree='1:00'
|
||
)
|
||
p.intervenants.set([user_bas])
|
||
p = Prestation.objects.create(
|
||
auteur=self.user,
|
||
famille=self.famille_litt,
|
||
date_prestation=auj,
|
||
duree='0:00', manque=True,
|
||
)
|
||
# Cette famille est du littoral, mais n'a pas Lise Dubas comme référente
|
||
Famille.objects.create_famille(
|
||
equipe='littoral',
|
||
nom='Tintin', rue='Château1', npa=2000, localite='Moulinsart',
|
||
)
|
||
months = [Month(date.today().year, date.today().month)]
|
||
stats = StatistiquesView(
|
||
date_start=date.today().replace(day=1),
|
||
date_end=(date.today().replace(day=1) + timedelta(days=35)).replace(day=1),
|
||
).get_stats(months)
|
||
self.assertEqual(stats['familles']['familles_evaluees']['total'], 3)
|
||
self.assertEqual(stats['familles']['enfants_evalues']['total'], 3)
|
||
self.assertEqual(stats['familles']['rdv_manques']['total'], 1)
|
||
|
||
def test_total_mensuel(self):
|
||
"""Test Famille.total_mensuel() method."""
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
auj = date.today()
|
||
mois_suiv = auj + timedelta(days=31)
|
||
self.assertEqual(famille.total_mensuel(auj), timedelta(0))
|
||
Prestation.objects.bulk_create([
|
||
Prestation(
|
||
auteur=self.user, famille=famille, date_prestation=date(auj.year, auj.month, 1), duree='1:30'
|
||
),
|
||
Prestation(
|
||
auteur=self.user, famille=famille, date_prestation=date(auj.year, auj.month, 25), duree='0:15'
|
||
),
|
||
# Not included in this month
|
||
Prestation(
|
||
auteur=self.user, famille=famille, date_prestation=date(mois_suiv.year, mois_suiv.month, 1),
|
||
duree='0:15'
|
||
),
|
||
])
|
||
self.assertEqual(famille.total_mensuel(auj), timedelta(minutes=105))
|
||
|
||
def test_total_prestations(self):
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
user = Utilisateur.objects.get(nom='Duhaut')
|
||
my_group = Group.objects.get(name='aemo')
|
||
my_group.user_set.add(user)
|
||
prestation_data = {
|
||
'auteur': self.user, 'famille': famille, 'date_prestation': date(2019, 3, 1),
|
||
'lib_prestation': LibellePrestation.objects.get(code='aemo01'),
|
||
}
|
||
Prestation.objects.bulk_create([
|
||
Prestation(**{**prestation_data, 'duree': '3:40'}),
|
||
Prestation(**{**prestation_data, 'duree': '6:40'}),
|
||
# Not included in this month
|
||
Prestation(**{**prestation_data, 'date_prestation': date(2019, 4, 1), 'duree': '2:00'}),
|
||
])
|
||
for p in Prestation.objects.filter(famille=famille):
|
||
p.intervenants.set([user])
|
||
|
||
self.assertEqual(format_duree(user.total_mensuel('aemo', 3, 2019)), '10:20')
|
||
self.assertEqual(format_duree(user.totaux_mensuels('aemo', 2019)[3]), '02:00')
|
||
self.assertEqual(format_duree(user.total_annuel('aemo', 2019)), '12:20')
|
||
totaux_2019 = Prestation.temps_totaux_mensuels(2019)
|
||
self.assertEqual(totaux_2019[0], timedelta())
|
||
self.assertEqual(format_duree(totaux_2019[2]), '10:20')
|
||
self.assertEqual(format_duree(totaux_2019[3]), '02:00')
|
||
self.assertEqual(format_duree(Prestation.temps_total_general(2019)), '12:20')
|
||
|
||
user.user_permissions.add(Permission.objects.get(codename='export_stats'))
|
||
self.client.force_login(user)
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '3', 'annee': '2019'})
|
||
self.assertEqual(format_duree(exp._total_spe['eval']), '10:20')
|
||
|
||
def test_export_prestations_decembre(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('export-prestation'), {'mois': '12', 'annee': '2019'})
|
||
self.assertEqual(response.status_code, 200)
|
||
|
||
@freeze_time("2020-12-14")
|
||
def test_affichage_prestation(self):
|
||
famille = Famille.objects.get(nom='Tournesol')
|
||
auj = date.today()
|
||
self.assertEqual(famille.total_mensuel(auj), timedelta(0))
|
||
user_haut = Utilisateur.objects.get(nom='Duhaut')
|
||
user_haut.taux_activite = 100.0
|
||
user_haut.save()
|
||
Prestation.objects.bulk_create([
|
||
Prestation(auteur=user_haut, famille=famille,
|
||
date_prestation=date(auj.year, 3, 1), duree='1:45'),
|
||
Prestation(auteur=user_haut, famille=famille,
|
||
date_prestation=date(auj.year, 5, 25), duree='0:15'),
|
||
# Not included in this month
|
||
Prestation(auteur=user_haut, famille=famille,
|
||
date_prestation=date(auj.year, 7, 1), duree='0:15'),
|
||
])
|
||
for p in Prestation.objects.filter(famille=famille):
|
||
p.intervenants.set([user_haut])
|
||
|
||
self.user.user_permissions.add(Permission.objects.get(codename='export_stats'))
|
||
self.client.force_login(self.user)
|
||
response = self.client.get(reverse('stats-prestations'))
|
||
data = response.context['intervenants'][user_haut]
|
||
self.assertEqual(format_duree(data['heures_prestees'][2]), '01:45')
|
||
self.assertEqual(format_duree(data['heures_prestees'][4]), '00:15')
|
||
self.assertEqual(format_duree(data['heures_prestees'][6]), '00:15')
|
||
|
||
self.assertEqual(format_duree(data['tot_prestees']), '02:15')
|
||
self.assertEqual(format_duree(response.context['totaux_prest_mensuels'][Month(auj.year, 3)]['total']), '01:45')
|
||
self.assertEqual(format_duree(response.context['total_gen']), '02:15')
|
||
|
||
@skip("This statistic is currently deactivated")
|
||
def test_stats_interv(self):
|
||
last_year = date.today().year - 1
|
||
famille = Famille.objects.get(nom='Haddock')
|
||
famille.suivi.date_debut_suivi = date(last_year, 2, 1)
|
||
famille.suivi.save()
|
||
user_bas = Utilisateur.objects.get(nom='Dubas')
|
||
self.client.force_login(self.user_admin)
|
||
params = '&'.join(
|
||
f'{key}={val}' for key, val in {
|
||
'start_year': last_year, 'start_month': '3', 'end_year': last_year, 'end_month': '5'
|
||
}.items()
|
||
)
|
||
response = self.client.get(reverse('stats-interv') + '?' + params)
|
||
self.assertEqual(response.context['interv_spe'][user_bas]['num_familles']['total'], 1)
|
||
|
||
def test_stats_par_niveau(self):
|
||
auj = date.today()
|
||
Niveau.objects.create(
|
||
famille=self.famille_litt, niveau_interv=2, date_debut=auj - timedelta(days=1)
|
||
)
|
||
# Niveau obsolète
|
||
Niveau.objects.create(
|
||
famille=self.famille_litt, niveau_interv=1,
|
||
date_debut=auj - timedelta(days=360), date_fin=auj - timedelta(days=100)
|
||
)
|
||
Prestation.objects.create(
|
||
famille=self.famille_litt, auteur=self.user, date_prestation=auj,
|
||
lib_prestation=LibellePrestation.objects.get(code='aemo04'),
|
||
duree=timedelta(minutes=90)
|
||
)
|
||
|
||
ilya2mois = auj - timedelta(days=60)
|
||
params = '&'.join(
|
||
f'{key}={val}' for key, val in {
|
||
'start_year': ilya2mois.year, 'start_month': ilya2mois.month,
|
||
'end_year': auj.year, 'end_month': auj.month,
|
||
}.items()
|
||
)
|
||
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.get(reverse('stats-niveaux') + '?' + params)
|
||
self.assertEqual(response.status_code, 200)
|
||
self.assertEqual(
|
||
response.context['stats'][2]['aemo04'][Month.from_date(auj)], timedelta(minutes=90)
|
||
)
|
||
self.assertEqual(
|
||
response.context['stats'][2]['aemo04']['total'], timedelta(minutes=90)
|
||
)
|
||
|
||
|
||
class ExportTests(InitialDataMixin, TestCase):
|
||
|
||
def setUp(self):
|
||
self.client.force_login(self.user_admin)
|
||
self.cfg_date = date(2019, 10, 3)
|
||
self.cfg_sheet = 'En_cours_{}.{}'.format(self.cfg_date.month, self.cfg_date.year)
|
||
self.cfg_export_month = {'mois': self.cfg_date.month, 'annee': self.cfg_date.year}
|
||
|
||
self.entetes_communs = [
|
||
'Institution', 'Prestation', 'Nom', 'Prenom', 'Genre', 'Date de naissance', 'Adresse', 'NPA', 'Localité',
|
||
'Canton', 'OPE', 'Nom mère', 'Prénom mère', 'Nom père', 'Prénom père', 'Autorité parentale',
|
||
'Statut marital', 'Statut financier', 'Fam. monopar.', 'Nbre enfants',
|
||
'Date demande', 'Provenance', 'Motif demande', 'Début suivi'
|
||
]
|
||
|
||
self.entetes_nouveaux = self.entetes_communs
|
||
self.entetes_en_cours = self.entetes_communs + ['H. Évaluation', 'H. Suivi', 'H. Prest. gén.']
|
||
self.entetes_termines = (self.entetes_communs +
|
||
['Date fin suivi', 'Motif fin suivi', 'Destination', 'Total heures'])
|
||
|
||
self.enf_suivi = Role.objects.get(nom='Enfant suivi', est_famille=True)
|
||
self.role_pere = Role.objects.get(nom='Père', est_famille=True)
|
||
self.role_mere = Role.objects.get(nom='Mère', est_famille=True)
|
||
|
||
def test_entete_nouveux_suivis(self):
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Nouveaux_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 1)
|
||
self.assertEqual(exp.sheets[sheet_name][0], self.entetes_nouveaux)
|
||
|
||
def test_entete_suivis_en_cours(self):
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'En_cours_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 1)
|
||
self.assertEqual(exp.sheets[sheet_name][0], self.entetes_en_cours)
|
||
|
||
def test_entete_suivis_termines(self):
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Terminés_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 1)
|
||
self.assertEqual(exp.sheets[sheet_name][0], self.entetes_termines)
|
||
|
||
def test_export_prestations_decembre(self):
|
||
self.client.force_login(self.user_admin)
|
||
response = self.client.post(reverse('export-prestation'), {'mois': '12', 'annee': '2019'})
|
||
self.assertEqual(response.status_code, 200)
|
||
|
||
def test_date_nouveau_suivi(self):
|
||
fam1 = self.create_famille(name='Haddock')
|
||
fam1.suivi.date_demande = '2019-09-20'
|
||
fam1.suivi.save()
|
||
|
||
fam2 = self.create_famille(name='Tournesol')
|
||
fam2.suivi.date_demande = '2019-10-20'
|
||
fam2.suivi.save()
|
||
|
||
fam3 = self.create_famille(name='Castafiore')
|
||
fam3.suivi.date_demande = '2019-11-20'
|
||
fam3.suivi.save()
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Nouveaux_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 2)
|
||
self.assertEqual([line[2] for line in exp.sheets[sheet_name]], ['Nom', 'Tournesol'])
|
||
|
||
def test_date_suivi_en_cours(self):
|
||
fam1 = self.create_famille(name='Haddock')
|
||
fam1.suivi.date_demande = '2019-09-20'
|
||
fam1.suivi.save()
|
||
|
||
fam2 = self.create_famille(name='Tournesol')
|
||
fam2.suivi.date_demande = '2019-10-20'
|
||
fam2.suivi.save()
|
||
|
||
fam3 = self.create_famille(name='Castafiore')
|
||
fam3.suivi.date_demande = '2019-11-20'
|
||
fam3.suivi.save()
|
||
|
||
self.benef1 = dict(nom='Haddock', date_admission='2019-10-02')
|
||
self.benef2 = dict(nom='Tournesol', date_admission='2019-09-30')
|
||
|
||
def test_date_suivi_termine(self):
|
||
fam1 = self.create_famille(name='Haddock')
|
||
fam1.suivi.date_demande = '2019-09-20'
|
||
fam1.suivi.date_fin_suivi = '2019-10-31'
|
||
fam1.suivi.save()
|
||
|
||
fam2 = self.create_famille(name='Tournesol')
|
||
fam2.suivi.date_demande = '2019-10-20'
|
||
fam2.suivi.save()
|
||
|
||
fam3 = self.create_famille(name='Castafiore')
|
||
fam3.suivi.date_demande = '2019-11-20'
|
||
fam3.suivi.date_fin_suivi = '2019-12-31'
|
||
fam3.suivi.save()
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Terminés_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 2)
|
||
self.assertEqual([line[2] for line in exp.sheets[sheet_name]], ['Nom', 'Haddock'])
|
||
|
||
def test_un_enfant_par_ligne(self):
|
||
fam = self.create_famille()
|
||
fam.suivi.date_demande = '2019-10-20'
|
||
fam.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=fam, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom='Haddock', prenom='Ursule', genre='M', date_naissance=date(2008, 11, 6),
|
||
)
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Nouveaux_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 3)
|
||
self.assertEqual(
|
||
[(line[2], line[3]) for line in exp.sheets['Nouveaux_10.2019']],
|
||
[('Nom', 'Prenom'), ('Haddock', 'Ursule'), ('Haddock', 'Toto')]
|
||
)
|
||
|
||
def test_repartition_temps_total_prestation_mensuel_entre_enfants(self):
|
||
fam = self.create_famille()
|
||
fam.suivi.date_demande = '2019-10-20'
|
||
fam.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=fam, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom='Haddock', prenom='Ursule', genre='M', date_naissance=date(2008, 11, 6),
|
||
)
|
||
aemo01 = LibellePrestation.objects.get(code='aemo01')
|
||
Prestation.objects.bulk_create([
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 21), lib_prestation=aemo01, duree='3:40'
|
||
),
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 22), lib_prestation=aemo01, duree='6:40'
|
||
),
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 30), lib_prestation=aemo01, duree='2:00'
|
||
),
|
||
])
|
||
for prest in Prestation.objects.all():
|
||
prest.intervenants.add(self.user_aemo)
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'En_cours_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 3)
|
||
self.assertEqual(
|
||
[(line[2], line[3], line[24]) for line in exp.sheets[sheet_name]],
|
||
[('Nom', 'Prenom', 'H. Évaluation'),
|
||
('Haddock', 'Ursule', timedelta(hours=6, minutes=10)),
|
||
('Haddock', 'Toto', timedelta(hours=6, minutes=10)),
|
||
]
|
||
)
|
||
|
||
def test_export_nouvelle_famille(self):
|
||
fam = self.create_famille()
|
||
fam.suivi.date_demande = '2019-10-20'
|
||
fam.suivi.date_debut_suivi = '2019-10-21'
|
||
fam.suivi.motif_demande = ['integration']
|
||
fam.suivi.save()
|
||
Prestation.objects.bulk_create([
|
||
Prestation(auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 21), duree='3:40'),
|
||
Prestation(auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 22), duree='6:40'),
|
||
# Not included in this month
|
||
Prestation(auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 11, 1), duree='2:00'),
|
||
])
|
||
self.assertEqual(Prestation.objects.filter(famille=fam).count(), 3)
|
||
for p in Prestation.objects.filter(famille=fam):
|
||
p.intervenants.set([self.user_aemo])
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
sheet_name = 'Nouveaux_10.2019'
|
||
self.assertEqual(len(exp.sheets[sheet_name]), 2)
|
||
self.assertEqual(
|
||
exp.sheets[sheet_name][1],
|
||
['Fondation Transit', 'AEMO', 'Haddock', 'Toto', 'M', '16.02.2010', 'Château1', '2000', 'Moulinsart', 'NE',
|
||
'Sybarnez Tina', '', '', 'Haddock', 'Archibald', 'Conjointe', 'Divorcé', '', 'NON', 1,
|
||
'20.10.2019', '', 'Aide à l’intégration', '21.10.2019']
|
||
)
|
||
|
||
def test_export_total_prestation_mois_courant(self):
|
||
fam = self.create_famille()
|
||
fam.suivi.date_demande = '2019-10-20'
|
||
fam.suivi.save()
|
||
aemo01 = LibellePrestation.objects.get(code='aemo01')
|
||
Prestation.objects.bulk_create([
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 21), lib_prestation=aemo01, duree='3:40'
|
||
),
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 10, 22), lib_prestation=aemo01, duree='6:40'
|
||
),
|
||
# Not included in this month
|
||
Prestation(
|
||
auteur=self.user_aemo, famille=fam, date_prestation=date(2019, 11, 1), lib_prestation=aemo01, duree='2:00'
|
||
),
|
||
])
|
||
for p in Prestation.objects.filter(famille=fam):
|
||
p.intervenants.set([self.user_aemo])
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '10', 'annee': '2019'})
|
||
self.assertEqual(len(exp.sheets['En_cours_10.2019']), 2)
|
||
self.assertEqual(exp.sheets['En_cours_10.2019'][1][24], timedelta(hours=10, minutes=20))
|
||
|
||
def test_export_prest_gen(self):
|
||
familles = [self.create_famille('Fam_{}'.format(i)) for i in range(5)]
|
||
for famille in familles:
|
||
famille.suivi.date_demande = date(2019, 10, 1)
|
||
famille.suivi.save()
|
||
prestation_data = {
|
||
'auteur': self.user_aemo, 'famille': None, 'date_prestation': date(2019, 10, 21),
|
||
'lib_prestation': LibellePrestation.objects.get(code='aemo03')
|
||
}
|
||
Prestation.objects.create(**{**prestation_data, 'duree': '6:50'})
|
||
Prestation.objects.create(**{**prestation_data, 'duree': '3:50'})
|
||
|
||
for prest in Prestation.objects.all():
|
||
prest.intervenants.add(self.user_aemo)
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), self.cfg_export_month)
|
||
self.assertEqual(len(exp.sheets[self.cfg_sheet]), 6)
|
||
self.assertEqual(format_duree(exp._total_spe['gen']), '10:40')
|
||
# Les 10h40 sont divisées par le nombre d'enfants suivis (= 5 * 2h08):
|
||
self.assertEqual(exp.sheets[self.cfg_sheet][1][26], timedelta(hours=2, minutes=8))
|
||
self.assertEqual(exp.sheets[self.cfg_sheet][2][26], timedelta(hours=2, minutes=8))
|
||
self.assertEqual(exp.sheets[self.cfg_sheet][3][26], timedelta(hours=2, minutes=8))
|
||
self.assertEqual(exp.sheets[self.cfg_sheet][4][26], timedelta(hours=2, minutes=8))
|
||
self.assertEqual(exp.sheets[self.cfg_sheet][5][26], timedelta(hours=2, minutes=8))
|
||
|
||
def test_export_evaluation(self):
|
||
familles = [self.create_famille('Fam_{}'.format(i)) for i in range(3)]
|
||
for famille in familles:
|
||
famille.suivi.date_demande = date(2019, 10, 1)
|
||
famille.suivi.save()
|
||
prestation_data = {
|
||
'auteur': self.user_aemo, 'date_prestation': date(2019, 10, 21),
|
||
'lib_prestation': LibellePrestation.objects.get(code='aemo01'),
|
||
}
|
||
Prestation.objects.bulk_create([
|
||
Prestation(**{**prestation_data, 'famille': familles[0], 'duree': '6:50'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[0], 'duree': '1:00'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[1], 'duree': '1:25'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[2], 'duree': '4:40'}),
|
||
])
|
||
for prest in Prestation.objects.all():
|
||
prest.intervenants.add(self.user_aemo)
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), self.cfg_export_month)
|
||
sheet_name = exp.sheets[self.cfg_sheet]
|
||
self.assertEqual(len(sheet_name), 4)
|
||
self.assertEqual(sheet_name[1][24], timedelta(hours=7, minutes=50))
|
||
self.assertEqual(sheet_name[2][24], timedelta(hours=1, minutes=25))
|
||
self.assertEqual(sheet_name[3][24], timedelta(hours=4, minutes=40))
|
||
self.assertEqual(format_duree(exp._total_spe['eval']), '13:55')
|
||
|
||
def test_export_suivi(self):
|
||
familles = [self.create_famille('Fam_{}'.format(i)) for i in range(3)]
|
||
for famille in familles:
|
||
famille.suivi.date_demande = date(2019, 10, 1)
|
||
famille.suivi.save()
|
||
prestation_data = dict(
|
||
{'auteur': self.user_aemo, 'date_prestation': date(2019, 10, 21),
|
||
'lib_prestation': LibellePrestation.objects.get(code='aemo02')}
|
||
)
|
||
Prestation.objects.bulk_create([
|
||
Prestation(**{**prestation_data, 'famille': familles[0], 'duree': '1:10'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[0], 'duree': '2:20'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[1], 'duree': '3:30'}),
|
||
Prestation(**{**prestation_data, 'famille': familles[2], 'duree': '4:45'}),
|
||
])
|
||
for prest in Prestation.objects.all():
|
||
prest.intervenants.add(self.user_aemo)
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), self.cfg_export_month)
|
||
sheet_name = exp.sheets[self.cfg_sheet]
|
||
self.assertEqual(len(sheet_name), 4)
|
||
self.assertEqual(sheet_name[1][25], timedelta(hours=3, minutes=30))
|
||
self.assertEqual(sheet_name[2][25], timedelta(hours=3, minutes=30))
|
||
self.assertEqual(sheet_name[3][25], timedelta(hours=4, minutes=45))
|
||
self.assertEqual(format_duree(exp._total_spe['suivi']), '11:45')
|
||
|
||
def test_export_authorization(self):
|
||
self.client.force_login(self.user_externe)
|
||
# Test denied access without export_stats permission
|
||
with self.assertLogs('django.request', level='WARNING'):
|
||
response = self.client.get(reverse('export-prestation'))
|
||
self.assertEqual(response.status_code, 403)
|
||
|
||
self.user_externe.user_permissions.add(Permission.objects.get(codename='export_stats'))
|
||
# Test default selected options in export form
|
||
with patch('aemo.views.date') as mock_date:
|
||
mock_date.today.return_value = date(2019, 7, 3)
|
||
response = self.client.get(reverse('export-prestation'))
|
||
self.assertContains(
|
||
response,
|
||
'<option value="6" selected>juin</option>'
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<option value="2019" selected>2019</option>'
|
||
)
|
||
|
||
mock_date.today.return_value = date(2020, 1, 30)
|
||
response = self.client.get(reverse('export-prestation'))
|
||
self.assertContains(
|
||
response,
|
||
'<option value="12" selected>décembre</option>'
|
||
)
|
||
self.assertContains(
|
||
response,
|
||
'<option value="2019" selected>2019</option>'
|
||
)
|
||
|
||
response = self.client.post(reverse('export-prestation'), data={'mois': '2', 'annee': '2019'})
|
||
self.assertEqual(response['Content-Type'], openxml_contenttype)
|
||
self.assertEqual(
|
||
response['Content-Disposition'],
|
||
'attachment; filename="aemo_reporting_02_2019.xlsx"'
|
||
)
|
||
|
||
def test_openxml_export_sheets(self):
|
||
# "Nouvelle" famille
|
||
famille = Famille.objects.create_famille(
|
||
equipe='littoral',
|
||
nom='NouvelleFamille', rue='Château 4', npa=2000, localite='Moulinsart',
|
||
)
|
||
famille.suivi.date_demande = '2019-02-10'
|
||
# famille.suivi.date_fin_suivi = '2019-05-30'
|
||
famille.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom='NouvelleFamille', prenom='Hégésipe', genre='M', date_naissance=date(1996, 2, 16)
|
||
)
|
||
|
||
# Famille "en cours"
|
||
famille = Famille.objects.create_famille(
|
||
equipe='littoral',
|
||
nom='FamilleEnCours', rue='Château 5', npa=2000, localite='Moulinsart',
|
||
autorite_parentale='conjointe', statut_marital='divorce', monoparentale=False,
|
||
)
|
||
famille.suivi.date_demande = '2019-01-01'
|
||
famille.suivi.date_debut_suivi = '2019-01-28'
|
||
ope_service = Service.objects.create(sigle="OPEC")
|
||
famille.suivi.ope_referent = Contact.objects.create(
|
||
nom="Duplain", prenom="Irma", service=ope_service
|
||
)
|
||
famille.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=Role.objects.get(nom='Enfant suivi'),
|
||
nom='FamilleEnCours', prenom='Alain', genre='M', date_naissance=date(2003, 4, 23),
|
||
localite='Moulinsart',
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=self.role_mere,
|
||
nom='FamilleEnCours', prenom='Judith', genre='F', date_naissance=date(1974, 11, 2)
|
||
)
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=self.role_pere,
|
||
nom='NomDuPere', prenom='Hans', genre='M', date_naissance=date(1968, 3, 13)
|
||
)
|
||
|
||
# Famille "terminée"
|
||
famille = Famille.objects.create_famille(
|
||
nom='FamilleTerminée', rue='Château 6', npa=2000, localite='Moulinsart',
|
||
)
|
||
famille.suivi.date_demande = '2018-10-02'
|
||
famille.suivi.date_debut_suivi = '2018-11-11'
|
||
famille.suivi.date_fin_suivi = '2019-02-20'
|
||
famille.suivi.motif_fin_suivi = 'relai'
|
||
famille.suivi.save()
|
||
Personne.objects.create_personne(
|
||
famille=famille, role=self.enf_suivi,
|
||
nom='FamilleTerminée', prenom='Jeanne', genre='F', date_naissance=date(1998, 12, 14)
|
||
)
|
||
|
||
self.client.force_login(self.user_admin)
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '2', 'annee': '2019'})
|
||
|
||
self.assertEqual(len(exp.sheets['En_cours_02.2019']), 4)
|
||
self.assertEqual(exp.sheets['En_cours_02.2019'][0], self.entetes_en_cours)
|
||
self.assertEqual(
|
||
exp.sheets['En_cours_02.2019'][1],
|
||
['Fondation Transit', 'AEMO', 'FamilleEnCours', 'Alain', 'M', '23.04.2003', '', '', 'Moulinsart', 'NE',
|
||
'Duplain Irma', 'FamilleEnCours', 'Judith', 'NomDuPere', 'Hans', 'Conjointe', 'Divorcé', '', 'NON', 1,
|
||
'01.01.2019', '', '', '28.01.2019',
|
||
timedelta(0), timedelta(0), timedelta(0)]
|
||
)
|
||
self.assertEqual(
|
||
[(line[2], line[3]) for line in exp.sheets['En_cours_02.2019'][1:]],
|
||
[('FamilleEnCours', 'Alain'), ('FamilleTerminée', 'Jeanne'), ('NouvelleFamille', 'Hégésipe')]
|
||
)
|
||
|
||
self.assertEqual(len(exp.sheets['Nouveaux_02.2019']), 2)
|
||
self.assertEqual(exp.sheets['Nouveaux_02.2019'][0], self.entetes_nouveaux)
|
||
self.assertEqual(
|
||
exp.sheets['Nouveaux_02.2019'][1],
|
||
['Fondation Transit', 'AEMO', 'NouvelleFamille', 'Hégésipe', 'M', '16.02.1996', '', '', '', 'NE',
|
||
'', '', '', '', '', '', '', '', '', 1,
|
||
'10.02.2019', '', '', ''
|
||
]
|
||
)
|
||
self.assertEqual(len(exp.sheets['Terminés_02.2019']), 2)
|
||
self.assertEqual(exp.sheets['Terminés_02.2019'][0], self.entetes_termines)
|
||
self.assertEqual(
|
||
exp.sheets['Terminés_02.2019'][1],
|
||
['Fondation Transit', 'AEMO', 'FamilleTerminée', 'Jeanne', 'F', '14.12.1998', '', '', '', 'NE',
|
||
'', '', '', '', '', '', '', '', '', 1,
|
||
'02.10.2018', '', '', '11.11.2018',
|
||
'20.02.2019', 'Relai vers autre service', '', timedelta(0)
|
||
]
|
||
)
|
||
|
||
famille = Famille.objects.get(nom='NouvelleFamille')
|
||
famille.suivi.motif_fin_suivi = 'erreur'
|
||
famille.suivi.date_fin_suivi = date(2019, 2, 17)
|
||
famille.suivi.save()
|
||
|
||
famille = Famille.objects.get(nom='FamilleTerminée')
|
||
famille.suivi.motif_fin_suivi = 'erreur'
|
||
famille.suivi.date_fin_suivi = date(2019, 2, 17)
|
||
famille.suivi.save()
|
||
|
||
exp = TestExporter()
|
||
with patch('aemo.views.ExportReporting', new=exp):
|
||
self.client.post(reverse('export-prestation'), {'mois': '2', 'annee': '2019'})
|
||
# Plus de famille, puisque les motifs de fin de suivi "erreur" ne sont pas pris en compte
|
||
self.assertEqual(len(exp.sheets['Nouveaux_02.2019']), 1)
|
||
self.assertEqual(len(exp.sheets['Terminés_02.2019']), 1)
|
||
# 'NouvelleFamille' plus exportée
|
||
self.assertEqual(len(exp.sheets['En_cours_02.2019']), 2)
|