passerelle/passerelle/contrib/solis_afi_mss/models.py

275 lines
9.9 KiB
Python

# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2020 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from urllib.parse import urljoin
from django.db import models
from django.utils.translation import ugettext_lazy as _
from passerelle.base.models import BaseResource, HTTPResource
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
TAX_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
"type": "object",
'properties': {
'email': {
'description': "Agent's email address",
'type': 'string',
},
'indexImposition': {
'description': 'Tax index',
'type': 'string',
},
'anneeImposition': {
'description': 'Year of taxation (YYYY)',
'type': 'string',
},
'nombrePartImposition': {
'description': 'Number of tax shares',
'type': 'string',
},
'montantImposition': {
'description': 'Tax amount',
'type': 'string',
},
}
}
DEMAND_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
"type": "object",
'properties': {
'email': {
'description': "Agent's email address",
'type': 'string',
},
'codeTypeAide': {
'description': 'Allowance type code',
'type': 'string',
},
'natureTypeAide': {
'description': 'Nature of the allowance (A, P or S)',
'type': 'string',
},
'individusConcernes': {
'description': "List of related family member indexes separated by ':'",
'type': 'string',
'pattern': r'^[0-9 :]+$'
},
'dateDebut': {
'description': 'Start date (YYYY-MM-DD)"',
'type': 'string',
},
'dateFin': {
'description': 'End date (YYYY-MM-DD)',
'type': 'string',
},
'montantFacture': {
'description': 'Invoice amount',
'type': 'string',
},
}
}
class SolisAfiMss(BaseResource, HTTPResource):
base_url = models.CharField(
max_length=256, blank=False,
verbose_name=_('Service URL'),
help_text=_('example: https://solis.mon-application.fr/api-mss-afi/')
)
category = _('Business Process Connectors')
class Meta:
verbose_name = _('Solis (mss-afi)')
def request(self, uri, params=None, json=None):
url = urljoin(self.base_url, uri)
headers = {'Accept': 'application/json'}
if json:
response = self.requests.post(url, json=json, headers=headers)
else:
response = self.requests.get(url, params=params, headers=headers)
if response.status_code // 100 != 2:
try:
json_content = response.json()
except ValueError:
json_content = None
raise APIError('error status:%s %r, content:%r' %
(response.status_code, response.reason, response.content[:1024]),
data={'status_code': response.status_code,
'json_content': json_content})
if response.status_code == 204 or not response.content: # 204 No Content
return None
try:
return response.json()
except ValueError:
raise APIError('invalid JSON content:%r' % response.content[:1024])
def check_status(self):
'''
Raise an exception if something goes wrong.
'''
return self.request('main/isAlive/')
def search_from_email(self, email):
response = self.request('afi/agent/rechercherParEmail/', params={'adresseMail': email})
index = response.get('indexAgent')
adults = []
for key in ('agent', 'conjointAgent'):
if response.get(key):
adults.append(response.get(key))
children = response.get('enfantsAgent')
for record in adults + children:
record['id'] = record.get('indexIndividu')
record['text'] = '%(prenom)s %(nom)s' % record
return index, adults, children
@endpoint(
display_category=_('Agent'), display_order=1,
perm='can_access', methods=['get'],
description=_('Retrieve family composition'),
parameters={
'email': {'description': _("Agent's email address")},
})
def family(self, request, email):
index, adults, children = self.search_from_email(email)
return {'data': adults + children}
@endpoint(
display_category=_('Agent'), display_order=1,
perm='can_access', methods=['get'],
description=_('Retrieve adults from family composition'),
parameters={
'email': {'description': _("Agent's email address")},
})
def adults(self, request, email):
adults, children = self.search_from_email(email)[1:]
return {'data': adults}
@endpoint(
display_category=_('Agent'), display_order=1,
perm='can_access', methods=['get'],
description=_('Retrieve children from family composition'),
parameters={
'email': {'description': _("Agent's email address")},
})
def children(self, request, email):
children = self.search_from_email(email)[2]
return {'data': children}
@endpoint(
display_category=_('Budget'), display_order=1,
perm='can_access', methods=['get'],
description=_('Retrieve the list of charges for an agent'),
parameters={
'email': {'description': _("Agent's email address")},
'year': {'description': _('Year of taxation (YYYY)')},
})
def taxes(self, request, email, year=None):
index = self.search_from_email(email)[0]
params = {'indexAgent': str(index)}
if year:
params['anneeImposition'] = year
uri = 'afi/budget/getImposition/'
else:
uri = 'afi/budget/getImpositionsParAgent/'
response = self.request(uri, params=params)
if year:
response = [response] if response else []
for record in response:
record['id'] = record.get('anneeImposition')
record['text'] = '%(anneeImposition)s: %(montantImposition)s' % record
return {'data': response}
@endpoint(
display_category=_('Budget'), display_order=2,
name='declare-tax', perm='can_access', methods=['post'],
description=_("Register an agent's tax for one year"),
post={'request_body': {'schema': {'application/json': TAX_SCHEMA}}})
def declare_tax(self, request, post_data):
email = post_data.pop('email')
post_data['indexAgent'] = str(self.search_from_email(email)[0])
response = self.request('afi/budget/declarerImpot/', json=post_data)
return {'data': response}
@endpoint(
display_category=_('Budget'), display_order=3,
name='simulate-quotient', perm='can_access', methods=['get'],
description=_(
'Simulate the calculation of a Quotient from the tax amount and the number of shares'),
parameters={
'email': {'description': _("Agent's email address")},
'year': {'description': _('Year of taxation (YYYY)')},
})
def simulate_quotient(self, request, code, nb_parts, amount):
params = {
'codeCalcul': code,
'nbrPartImposition': nb_parts,
'mntImposition': amount,
}
response = self.request('afi/budget/calculer/', params=params)
return {'data': response}
@endpoint(
display_category=_('Allowance'), display_order=1,
perm='can_access', methods=['get'],
description=_('Retrieve the list of allowance from an agent'),
parameters={
'email': {'description': _("Agent's email address")},
'text_template': {'description': _('Text template')},
})
def helps(self, request, email):
params = {'indexAgent': str(self.search_from_email(email)[0])}
response = self.request('afi/aide/getAidesParAgent/', params=params)
for record in response['aidesFinancieres']:
record['id'] = record.get('indexAideFinanciere')
record['text'] = '%(dateDemandeAide)s (%(suiviAide)s)' % record
return {'data': response['aidesFinancieres']}
@endpoint(
display_category=_('Allowance'), display_order=2,
name='demand-help', perm='can_access', methods=['post'],
description=_('Submit allowance for an agent'),
post={'request_body': {'schema': {'application/json': DEMAND_SCHEMA}}})
def demand_help(self, request, post_data):
email = post_data.pop('email')
index_agent, adults, children = self.search_from_email(email)
related_persons = []
for person in adults + children:
for index in [
x.strip() for x in post_data['individusConcernes'].split(':') if x.strip()]:
if str(person['indexIndividu']) == index:
related_persons.append({"indexIndividu": index})
post_data['indexAgent'] = str(index_agent)
post_data['individusConcernes'] = related_persons
response = self.request('afi/aide/deposer/', json=post_data)
return {'data': response}