Merge branch 'master' into nanterre-recette

This commit is contained in:
Thomas NOËL 2017-11-15 14:44:32 +01:00
commit 42f324b8a2
4 changed files with 152 additions and 4 deletions

View File

@ -956,6 +956,34 @@ def test_cles_de_federations(app, rsu_schema):
assert Entity.objects.filter(content__cles_de_federation__technocarte='idtechno').count() == 1
assert Entity.objects.filter(content__cles_de_federation__technocarte='idtechno').get().id == first_id
# suppression d'un individu
suppression_url = reverse('rsu-api-suppression-individu', kwargs={
'identifier': first_id})
response = app.post(suppression_url)
# impossible il y a toujours une clé
assert response.json['err'] == 1
assert len(response.json['errors']) == 1
# on supprimer la clé technocarte
response = app.post_json(update_url, params={
'cles_de_federation': {
'technocarte': ''
},
})
entities = Entity.objects.all()
relations = Relation.objects.all()
# on a initialement 2 individus avec 2 adresses
assert entities.count() == 4
# on retente
response = app.post(suppression_url)
# c'est ok
assert response.json['err'] == 0
# on vérifie qu'il n'y a plus qu'une fiche et qu'une adresse et qu'ils sont liés
assert entities.filter(schema__slug='individu').count() == 1
assert entities.filter(id=second_id).count() == 1
assert entities.filter(schema__slug='adresse').count() == 1
assert relations.count() == 1
assert relations.filter(left__id=second_id, schema__slug='habite').count() == 1
def test_separation(db, app, rsu_schema):
# création du premier adulte
@ -1039,6 +1067,23 @@ def test_separation(db, app, rsu_schema):
assert get_individu_adresse(second_adult) == second_adult_address
assert Entity.objects.filter(id=first_adult_address.id).count() == 0
# on ne peut supprimer aucun des deux
suppression_url = reverse('rsu-api-suppression-individu', kwargs={
'identifier': first_adult_id})
response = app.post(suppression_url)
# impossible il y a une union
assert response.json['err'] == 1
assert len(response.json['errors']) == 1
assert 'conjoint' in response.json['errors'][0]
suppression_url = reverse('rsu-api-suppression-individu', kwargs={
'identifier': second_adult_id})
response = app.post(suppression_url)
# impossible il y a une union
assert response.json['err'] == 1
assert response.json['err'] == 1
assert len(response.json['errors']) == 1
assert 'conjoint' in response.json['errors'][0]
# rattachement du premier enfant au premier adulte
enfant_url = reverse('rsu-api-declaration-responsabilite-legale',
kwargs={'identifier': first_adult_id})
@ -1062,6 +1107,24 @@ def test_separation(db, app, rsu_schema):
first_child = Entity.objects.get(id=first_child_id)
assert get_individu_adresse(first_child) == second_adult_address
# on ne peut supprimer le parent, il a un enfant et un conjoint
suppression_url = reverse('rsu-api-suppression-individu', kwargs={
'identifier': first_adult_id})
response = app.post(suppression_url)
# impossible il y a une union
assert response.json['err'] == 1
assert len(response.json['errors']) == 2
assert 'enfant' in response.json['errors'][0]
assert 'conjoint' in response.json['errors'][1]
# on ne peut supprimer l'enfant, il a un parent
suppression_url = reverse('rsu-api-suppression-individu', kwargs={
'identifier': first_child_id})
response = app.post(suppression_url)
# impossible il y a une union
assert response.json['err'] == 1
assert len(response.json['errors']) == 1
assert 'avec un parent' in response.json['errors'][0]
# rattachement du premier enfant au deuxième adulte
enfant_url = reverse('rsu-api-declaration-responsabilite-legale',
kwargs={'identifier': second_adult_id})

View File

@ -52,6 +52,17 @@ def test_list_doublons(nanterre_classic_family, app):
first_data = response.json['data'][0]
second_data = response.json['data'][1]
url = reverse('rsu-api-doublons') + '?score_min=90&limit=100'
response = app.get(url)
assert response.json['err'] == 0
assert 'more' not in response.json
assert 'cookie' not in response.json
assert len(response.json['data']) == 23 # Duplicate.objects.filter(score__gte=Decimal('0.9')).count()
for doublon in response.json['data']:
assert int(doublon['score']) >= 90
assert response.json['score_min'] == '90'
assert 'score_max' not in response.json
doublon_url = reverse('rsu-api-doublon', kwargs={'doublon_id': '%s %s' % (d.first_id,
d.second_id)})
response = app.get(doublon_url)

View File

@ -24,6 +24,7 @@ import time
import traceback
from dateutil.relativedelta import relativedelta
import datetime
from decimal import Decimal, InvalidOperation
from django.conf import settings
from django.shortcuts import get_object_or_404
@ -1393,6 +1394,51 @@ class Synchronisation(TransactionalView):
synchronization = Synchronisation.as_view()
class SuppressionIndividu(IndividuViewMixin, TransactionalView):
def post(self, request, identifier, format=None):
individu = self.get_individu(identifier)
# vérifie l'absence de relation et de fédérations
errors = []
parent_count = len(list(utils.parents(individu)))
if parent_count:
errors.append(u'cet individu a encore %d lien(s) avec un parent' % parent_count)
enfant_count = len(list(utils.enfants(individu)))
if enfant_count:
errors.append(u'cet individu a encore %d lien(s) avec un enfant' % enfant_count)
conjoint, rel = utils.conjoint(individu)
if conjoint:
errors.append(u'cet individu a un conjoint')
uuid_authentic = None
for application in individu.content['cles_de_federation']:
if application == 'authentic':
uuid_authentic = individu.content['cles_de_federation']['authentic']
else:
errors.append(u'cet individu a encore une clé de fédération avec %s' % application)
if errors:
return Response({
'err': 1,
'errors': errors,
})
adresses = utils.adresses(individu)
individu.delete()
# supprimer les adresses orphelines
for adresse, rel in adresses:
# left_relations ne devrait pas exister, mais dans le doute...
if not adresse.right_relations.exists() and not adresse.left_relations.exists():
adresse.delete()
response = {'err': 0}
if uuid_authentic:
response['cles_de_federation'] = {'authentic': uuid_authentic}
response['messages'] = [u'cette fiche avait une clé de fédération sur le portail '
u'internet: %s' % uuid_authentic]
return Response(response)
suppression_individu = SuppressionIndividu.as_view()
class SagaTiers(APIView):
def get(self, request, application, identifier, format=None):
app_dfn = utils.get_application(application)
@ -1845,6 +1891,21 @@ class DoublonsView(DoublonMixin, APIView):
elif dedup:
qs = qs.filter(state=models.Duplicate.STATE_DEDUP)
if 'score_min' in request.GET:
try:
score_min = Decimal(request.GET['score_min'])
except InvalidOperation:
pass
else:
qs = qs.filter(score__gte=score_min/100)
if 'score_max' in request.GET:
try:
score_max = Decimal(request.GET['score_max'])
except InvalidOperation:
pass
else:
qs = qs.filter(score__lte=score_max/100)
# recherche ciblée
if 'id' in request.GET:
try:
@ -1871,14 +1932,25 @@ class DoublonsView(DoublonMixin, APIView):
'err': 0,
'data': data[:limit],
}
params = {'limit': limit}
if 'score_min' in request.GET:
params['score_min'] = request.GET['score_min']
if 'score_max' in request.GET:
params['score_max'] = request.GET['score_max']
if false_positive:
params['false_positive'] = false_positive
if dedup:
params['dedup'] = dedup
content.update(params)
if len(data) > limit:
since = qs[limit - 1].created.isoformat()
max_id = qs[limit - 1].id
more_url = request.build_absolute_uri(reverse('rsu-api-doublons'))
cookie = '%s_%s' % (since, max_id)
more_url += '?' + urlencode({'limit': limit, 'cookie': cookie})
content['more'] = more_url
content['cookie'] = cookie
content['cookie'] = params['cookie'] = cookie
content['more'] = request.build_absolute_uri(reverse('rsu-api-doublons')) + '?' + urlencode(params)
return Response(content)
doublons = DoublonsView.as_view()

View File

@ -25,6 +25,8 @@ urlpatterns = [
url(r'^import_control/$', import_control, name='demo'),
url(r'^search/$', api_views.search, name='rsu-api-search'),
url(r'^individu/(?P<identifier>[-\w]+)/$', api_views.reseau, name='rsu-api-reseau'),
url(r'^individu/(?P<identifier>[-\w]+)/suppression/$', api_views.suppression_individu,
name='rsu-api-suppression-individu'),
url(r'^individu/(?P<identifier>[-\w]+)/liste/$', api_views.reseau_liste,
name='rsu-api-reseau-liste'),
url(r'^individu/(?P<identifier>[-\w]+)/journal/$', api_views.journal, name='rsu-api-journal'),