zoo/zoo/zoo_nanterre/qf.py

291 lines
11 KiB
Python

# -*- coding: utf-8 -*-
import logging
import re
import json
from zoo.models import Job
import requests
from django.utils.timezone import now
from django.conf import settings
from . import fragments
class QF(object):
ID_FRAGMENT = fragments.FragmentBuilder.ID_FRAGMENT
def __init__(self, timeout=None):
app = settings.ZOO_NANTERRE_APPLICATIONS['implicit']
self.url = app.get('rsu_ws_url', app['url'])
self.timeout = timeout or settings.ZOO_NANTERRE_RSU_TIMEOUT
def request(self, service, fragments):
msg = {
'metadonnees': {
'origine': 'agent',
'service': service,
'date-soumission': now().isoformat(' ').split('.')[0],
},
'fragments': fragments,
}
try:
response = requests.post(
self.url,
# on encode en UTF-8 pure, sans réencodage JSON
data=json.dumps(msg, ensure_ascii=False).encode('utf-8'),
timeout=self.timeout,
headers={
'Content-Type': 'application/json'
})
except requests.RequestException as e:
return None, u'Implicit connexion impossible: %r' % e
try:
data = response.json()
except ValueError as e:
return None, u'Implicit contenu non JSON: %s %r' % (response.status_code, response.text[:1024])
if response.status_code != 200:
return None, data
return data, None
def lire_quotients_valides(self, date_de_reference):
response, error = self.request('lire-quotients-valides', [{
self.ID_FRAGMENT: 1,
'type': 'donnees-lecture-quotients-valides',
'fragment': {
'date-reference': date_de_reference.isoformat(),
}
}])
if response:
for qf in response:
try:
qf['annee_imposition'] = str(int(re.findall(r'(\d+)', qf['libelle'])[0]) - 1)
except Exception:
qf['annee_imposition'] = 'inconnue'
return response, error
def simuler_qf(self,
nature_qf,
annee_imposition,
rfr,
nb_parts,
monoparentalite,
annee_imposition_concubin=None,
rfr_concubin=None,
nb_parts_concubin=None):
fragment = {
self.ID_FRAGMENT: 1,
'type': 'donnees-quotient-familial',
'fragment': {
'nature-qf': nature_qf,
'annee-imposition': annee_imposition,
'rfr': rfr,
'nb-parts': float(nb_parts),
'monoparentalite': monoparentalite,
'annee-imposition-concubin': annee_imposition_concubin,
'rfr-concubin': rfr_concubin,
'nb-parts-concubin': float(nb_parts_concubin) if nb_parts_concubin else None,
}
}
response, error = self.request('simuler-quotient-familial', [fragment])
if error:
return None, error
return response[0], None
def calcul_qf(self,
individu,
nature_qf,
annee_imposition,
rfr,
nb_parts,
monoparentalite,
annee_imposition_concubin=None,
rfr_concubin=None,
nb_parts_concubin=None):
parts = []
federation = individu.content['cles_de_federation'].get('implicit')
if not federation:
parts.append({
self.ID_FRAGMENT: 1,
'type': 'nouvel-adulte',
'fragment': fragments.individu_to_fragment(individu),
})
reference_key = 'beneficiaire'
reference = '@1'
else:
reference_key = 'id-metier'
reference = federation
fragment = {
self.ID_FRAGMENT: len(parts) + 1,
'type': 'donnees-quotient-familial',
'fragment': {
reference_key: reference,
'nature-qf': nature_qf,
'annee-imposition': annee_imposition,
'rfr': rfr,
'nb-parts': float(nb_parts),
'monoparentalite': monoparentalite,
'annee-imposition-concubin': annee_imposition_concubin,
'rfr-concubin': rfr_concubin,
'nb-parts-concubin': float(nb_parts_concubin) if nb_parts_concubin else None,
}
}
parts.append(fragment)
response, error = self.request('calcul-quotient-familial', parts)
if error:
return None, error
if isinstance(response, list):
if not federation:
federation = response[0]['id-metier']
individu.content['cles_de_federation']['implicit'] = federation
individu.save()
return response[1], None
else:
return response[0], None
else:
return None, 'Implicit calcul-qf réponse invalide: %r' % str(response)[:1024]
def lire_quotient_familial(self, individu, date_de_reference):
federation = individu.content['cles_de_federation'].get('implicit')
if not federation:
return [], None
fragment = {
self.ID_FRAGMENT: 1,
'type': 'donnees-lecture-quotient-familial',
'fragment': {
'id-metier': federation,
'date-reference': date_de_reference.isoformat(),
}
}
response, error = self.request('lire-quotient-familial', [fragment])
if error:
return None, error
if isinstance(response, list):
return response, None
else:
return None, ('Implicit lire-quotient-familial réponse invalide: %r'
% str(response)[:1024])
def editer_carte(self, individu, id_qf):
federation = individu.content['cles_de_federation'].get('implicit')
if not federation:
return None, u'Implicit editer-carte: pas de clé métier'
fragment = {
self.ID_FRAGMENT: 1,
'type': 'donnees-carte-quotient-familial',
'fragment': {
'id-metier': federation,
'id-qf': id_qf,
}
}
response, error = self.request('editer-carte-quotient-familial', [fragment])
if error:
return None, error
if not isinstance(response, dict) or 'lien' not in response:
return None, u'Implicit editer-carte réponse invalide: %s' % response
try:
url = str(response['lien'])
except Exception as e:
return None, u'Implicit editer-carte impossible de convertir le lien: %r' % response
try:
response = requests.get(url)
except requests.RequestException as e:
return None, (u'Implicit editer-carte connexion impossible pour récupérer le lien: '
'%s %r' % (url, e))
if response.status_code != 200:
return None, (u'Implicit editer-carte code non 200 sur récupération du lien: '
'%s %s %r' % (url, response.status_code, response.text[:1024]))
return response.content, None
class CalculQF(fragments.FragmentBuilder):
qf = None
service = 'calcul-quotient-familial'
state_on_network_error = Job.STATE_UNRECOVERABLE_ERROR
lock_individus = True
@classmethod
def create(cls, application, individu,
nature_qf,
annee_imposition,
rfr,
nb_parts,
monoparentalite,
annee_imposition_concubin=None,
rfr_concubin=None,
nb_parts_concubin=None,
meta=None):
self = super(CalculQF, cls).create(application, [individu], meta=meta)
federation = individu.content['cles_de_federation'].get('implicit')
if not federation:
self.nouvel_individu(individu)
reference_key = 'beneficiaire'
reference = '@1'
else:
reference_key = 'id-metier'
reference = federation
self.add_fragment({
'type': 'donnees-quotient-familial',
'fragment': {
reference_key: reference,
'nature-qf': nature_qf,
'annee-imposition': annee_imposition,
'rfr': rfr,
'nb-parts': float(nb_parts),
'monoparentalite': monoparentalite,
'annee-imposition-concubin': annee_imposition_concubin,
'rfr-concubin': rfr_concubin,
'nb-parts-concubin': float(nb_parts_concubin) if nb_parts_concubin else None,
}
})
return self
def handle_response_200(self, response, result, job):
individu = self.individus[0]
if isinstance(result, list) and len(self.fragments) == len(result):
if len(result) == 2:
federation = result[0]['id-metier']
individu.content['cles_de_federation']['implicit'] = federation
individu.save()
self.qf = result[1]
else:
self.qf = result[0]
return Job.STATE_SUCCESS
self.error = {
'code': 'response-is-invalid',
'content': result,
}
return Job.STATE_UNRECOVERABLE_ERROR
@classmethod
def calcul_qf(cls, individu,
nature_qf,
annee_imposition,
rfr,
nb_parts,
monoparentalite,
annee_imposition_concubin=None,
rfr_concubin=None,
nb_parts_concubin=None,
meta=None, transaction=None):
action = cls.create('implicit', individu,
nature_qf=nature_qf,
annee_imposition=annee_imposition,
rfr=rfr,
nb_parts=nb_parts,
monoparentalite=monoparentalite,
annee_imposition_concubin=annee_imposition_concubin,
rfr_concubin=rfr_concubin,
nb_parts_concubin=nb_parts_concubin,
meta=meta)
job = Job.create(action, transaction=transaction)
if job.state == Job.STATE_SUCCESS:
return action.qf, None
else:
return None, action.human_result