add actesweb connector (#22395)

This commit is contained in:
Josue Kouka 2018-03-30 15:13:32 +02:00 committed by Serghei Mihai
parent 7d97dd326d
commit 7d0dbcb654
10 changed files with 480 additions and 0 deletions

View File

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0006_resourcestatus'),
]
operations = [
migrations.CreateModel(
name='ActesWeb',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=50, verbose_name='Title')),
('description', models.TextField(verbose_name='Description')),
('slug', models.SlugField(unique=True)),
('log_level', models.CharField(default=b'INFO', max_length=10, verbose_name='Log Level', choices=[(b'NOTSET', b'NOTSET'), (b'DEBUG', b'DEBUG'), (b'INFO', b'INFO'), (b'WARNING', b'WARNING'), (b'ERROR', b'ERROR'), (b'CRITICAL', b'CRITICAL')])),
('users', models.ManyToManyField(to='base.ApiUser', blank=True)),
],
options={
'verbose_name': "ActesWeb - Demande d'acte d'\xe9tat civil",
},
),
]

View File

@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2018 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 __future__ import unicode_literals
import json
import os
import tempfile
from django.core.files.storage import default_storage
from django.template.loader import get_template
from django.utils.dateparse import parse_date
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from passerelle.base.models import BaseResource
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
class ActesWeb(BaseResource):
category = _('Civil Status Connectors')
class Meta:
verbose_name = u"ActesWeb - Demande d'acte d'état civil"
@property
def basepath(self):
return os.path.join(
default_storage.path('actesweb'), self.slug)
@endpoint(perm='can_access', methods=['post'], description=_('Create demand'))
def create(self, request, *args, **kwargs):
try:
payload = json.loads(request.body)
except (ValueError,):
raise APIError('Invalid payload format: json expected')
if payload.get('certificate_type') not in ('NA', 'DE', 'MA'):
raise APIError("Invalid <certificate_type>: expected ('NA', 'DE', 'MA')")
payload['event_date_start'] = parse_date(payload['event_date_start']).strftime('%Y%m%d')
template_name = 'actesweb/demand.txt'
demand_content = get_template(template_name).render(payload)
application_id = payload['application_id']
# create tmp dir
tmp_dir = os.path.join(self.basepath, 'tmp')
if not os.path.exists(tmp_dir):
if default_storage.directory_permissions_mode:
d_umask = os.umask(0)
try:
os.makedirs(tmp_dir, mode=default_storage.directory_permissions_mode)
except OSError:
pass
finally:
os.umask(d_umask)
else:
os.makedirs(tmp_dir)
filename = '%s.DEM' % now().strftime('%Y-%m-%d_%H-%M-%S_%f')
filepath = os.path.join(self.basepath, filename)
with tempfile.NamedTemporaryFile(dir=tmp_dir, suffix='.DEM', delete=False) as tpf:
tpf.write(demand_content)
tpf.flush()
os.fsync(tpf.file.fileno())
os.rename(tpf.name, filepath)
demand_id = '%s_%s' % (application_id, os.path.basename(filepath))
return {'data': {'demand_id': demand_id}}

View File

@ -0,0 +1,46 @@
CODAGE=TXT
TYPE=DEMANDE
VERSION=03
TYPE_DEMANDEUR={{applicant_type}}
PRIORITE={{application_priority}}
DEMANDEUR_CIVILITE={{applicant_title_label}}
DEMANDEUR_NOM={{application_priority}}
DEMANDEUR_NOM_USAGE={{applicant_usual_name}}
DEMANDEUR_PRENOMS={{applicant_firstnames}}
DEMANDEUR_ADRESSE1={{applicant_address_street}}
DEMANDEUR_ADRESSE2={{applicant_address_complement}}
DEMANDEUR_VILLE={{applicant_address_city}}
DEMANDEUR_PAYS={{applicant_address_country}}
DEMANDEUR_TEL={{applicant_phone}}
DEMANDEUR_ADR={{applicant_email}}
DEMANDE_NOM={{concerned_lastname}}
DEMANDE_PRENOMS={{concerned_firstnames}}
DEMANDE_DATE_EVENEMENT={{event_date_start}}
TYPE_DEMANDE={{document_type_label}}
ACTE={{certificate_type|default:"particulier"}}
NB={{document_copies}}
LIEN={{applicant_status}}
MANDANT_NOM=
MANDANT_PRENOMS=
LIEU_EVENEMENT={{event_city}}
REF_ACTE={{document_ref|default:"inconnu"}}
PERE_NOM={{concerned_parent1_lastname}}
PERE_PRENOMS={{concerned_parent1_firstnames}}
MERE_NOM={{concerned_parent2_lastname}}
MERE_PRENOMS={{concerned_parent2_firstnames}}
CONJOINT_NOM={{partner_lastname}}
CONJOINT_PRENOMS={{partner_firstnames}}
CONJOINT_PERE_NOM={{partner_parent1_lastname}}
CONJOINT_PERE_PRENOMS={{partner_parent1_firstnames}}
CONJOINT_MERE_NOM={{partner_parent2_lastname}}
CONJOINT_MERE_PRENOMS={{partner_parent2_firstnames}}
MOTIF={{application_reason}}
DEMANDE_SEXE={{concerned_sex}}
DPERE_SEXE={{concerned_parent1_sex}}
DMERE_SEXE={{concerned_parent2_sex}}
CONJOINT_SEXE={{partner_sex}}
CPERE_SEXE={{partner_parent1_sex}}
CMERE_SEXE={{partner_parent2_sex}}
{% spaceless %}
COMMENTAIRE={{application_comment}}
{% endspaceless %}

View File

@ -115,6 +115,7 @@ INSTALLED_APPS = (
'passerelle.base',
'passerelle.datasources',
# connectors
'passerelle.apps.actesweb',
'passerelle.apps.airquality',
'passerelle.apps.api_particulier',
'passerelle.apps.atos_genesys',

View File

@ -0,0 +1,50 @@
{
"applicant_address_city": "Nancy",
"applicant_address_complement": "Bat A",
"applicant_address_country": "France",
"applicant_address_county": "Meurthe-et-Moselle",
"applicant_address_street": "37 Rue du Cheval Blanc",
"applicant_address_zipcode": "54000",
"applicant_email": "chelsea@whatever.com",
"applicant_firstnames": "Kim Chelsea",
"applicant_lastname": "Whatever",
"applicant_name_usage": "nom d'epouse",
"applicant_phone": "+33 6 55 44 22 11",
"applicant_status": "concerne",
"applicant_title": "Mme",
"applicant_title_label": "Madame",
"applicant_usual_name": "Whatever",
"application_id": "N201610154",
"application_origin": "internet",
"application_reason": "They are just messy",
"application_time": "2016-10-20T14:41:20Z",
"certificate_type": "NA",
"certificate_type_label": "Acte de naissance",
"concerned_birth_city": "Harare",
"concerned_birth_country": "Zimbabwe",
"concerned_birth_county": "",
"concerned_birth_date": "1980-02-29",
"concerned_firstnames": "Kevin",
"concerned_lastname": "Whatever",
"concerned_name_usage": "",
"concerned_parent1_firstnames": "John Oliver",
"concerned_parent1_lastname": "Smith",
"concerned_parent1_name_usage": "Smith",
"concerned_parent1_title": "M",
"concerned_parent1_title_label": "Monsieur",
"concerned_parent1_usual_name": "Smith",
"concerned_parent2_firstnames": "Kim",
"concerned_parent2_lastname": "Smith",
"concerned_parent2_name_usage": "nom d'\u00e9pouse",
"concerned_parent2_title": "Mme",
"concerned_parent2_usual_name": "Smith",
"concerned_sex": "m",
"concerned_title": "M",
"concerned_usual_name": "Whatever",
"document_copies": "1",
"document_type": "CPI",
"document_type_label": "Copie Integrale",
"event_city": "Nancy",
"event_date_end": "",
"event_date_start": "2012-07-14"
}

View File

@ -0,0 +1,37 @@
{
"applicant_address_city": "Nancy",
"applicant_address_complement": "Bat A",
"applicant_address_country": "France",
"applicant_address_county": "Meurthe-et-Moselle",
"applicant_email": "chelsea@whatever.com",
"applicant_phone": "+33 6 55 44 22 11",
"applicant_address_street": "37 Rue du Cheval Blanc",
"applicant_address_zipcode": "54000",
"applicant_firstnames": "Kim Chelsea",
"applicant_lastname": "Whatever",
"applicant_name_usage": "nom d'epouse",
"applicant_status": "concerne",
"applicant_title": "Mme",
"applicant_title_label": "Madame",
"applicant_usual_name": "Whatever",
"application_id": "D201610171",
"application_origin": "internet",
"application_reason": "",
"application_time": "2016-10-20T14:41:20Z",
"certificate_type": "DE",
"certificate_type_label": "Acte de d\u00e9c\u00e8s",
"concerned_birth_city": "Harare",
"concerned_birth_country": "Zimbabwe",
"concerned_birth_county": "",
"concerned_birth_date": "1980-02-29",
"concerned_firstnames": "Kevin",
"concerned_lastname": "Whatever",
"concerned_sex": "m",
"concerned_title": "M",
"concerned_usual_name": "Whatever",
"document_copies": "1",
"document_type": "EXTSF",
"document_type_label": "Extrait sans filiation",
"event_city": "Nancy",
"event_date_start": "2012-07-14"
}

View File

@ -0,0 +1,68 @@
{
"applicant_address_city": "Nancy",
"applicant_address_complement": "Bat A",
"applicant_address_country": "France",
"applicant_address_county": "Meurthe-et-Moselle",
"applicant_email": "chelsea@whatever.com",
"applicant_phone": "+33 6 55 44 22 11",
"applicant_address_street": "37 Rue du Cheval Blanc",
"applicant_address_zipcode": "54000",
"applicant_firstnames": "Kim Chelsea",
"applicant_lastname": "Whatever",
"applicant_name_usage": "nom d'epouse",
"applicant_status": "concerne",
"applicant_title": "Mme",
"applicant_title_label": "Madame",
"applicant_usual_name": "Whatever",
"application_id": "M201610161",
"application_origin": "internet",
"application_reason": "Happy mariage",
"application_time": "2016-10-20T14:41:20Z",
"certificate_type": "MA",
"certificate_type_label": "Acte de naissance",
"concerned_birth_city": "Harare",
"concerned_birth_country": "Zimbabwe",
"concerned_birth_county": "",
"concerned_birth_date": "1980-02-29",
"concerned_firstnames": "Kevin",
"concerned_lastname": "Whatever",
"concerned_name_usage": "",
"concerned_parent1_firstnames": "John Oliver",
"concerned_parent1_lastname": "Smith",
"concerned_parent1_name_usage": "Smith",
"concerned_parent1_title": "M",
"concerned_parent1_title_label": "Monsieur",
"concerned_parent1_usual_name": "Smith",
"concerned_parent2_firstnames": "Kim",
"concerned_parent2_lastname": "Smith",
"concerned_parent2_name_usage": "nom d'\u00e9pouse",
"concerned_parent2_title": "Mme",
"concerned_parent2_usual_name": "Smith",
"concerned_sex": "m",
"concerned_title": "M",
"document_copies": "1",
"document_type": "CPI",
"document_type_label": "Copie Integrale",
"event_city": "Nancy",
"event_date_end": "",
"event_date_start": "2012-07-14",
"partner_birth_city": "Harare",
"partner_birth_country": "Zimbabwe",
"partner_birth_county": "",
"partner_birth_date": "1984-02-29",
"partner_firstnames": "Chelsea",
"partner_lastname": "Contrao",
"partner_name_usage": "",
"partner_parent1_firstnames": "Antonio",
"partner_parent1_lastname": "Scaramucci",
"partner_parent1_title": "M",
"partner_parent1_title_label": "Monsieur",
"partner_parent2_firstnames": "Marguerite",
"partner_parent2_lastname": "Scaramucci",
"partner_parent2_name_usage": "nom d'\u00e9pouse",
"partner_parent2_title": "Mme",
"partner_parent2_usual_name": "Gaye",
"partner_sex": "F",
"partner_title": "Mme",
"partner_usual_name": "Scaramucci"
}

171
tests/test_actesweb.py Normal file
View File

@ -0,0 +1,171 @@
# -*- coding: utf-8 -*-
# Passerelle - uniform access to data and services
# Copyright (C) 2018 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; exclude 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.deepcopy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import json
import io
import os
import shutil
import pytest
import utils
from passerelle.apps.actesweb.models import ActesWeb
def get_test_base_dir(name):
return os.path.join(os.path.dirname(__file__), 'data', name)
def get_file_from_test_base_dir(filename):
path = os.path.join(get_test_base_dir('actesweb'), filename)
with open(path, 'rb') as fd:
return fd.read()
@pytest.fixture
def actesweb(db):
return utils.make_resource(ActesWeb, **{'slug': 'test'})
@pytest.fixture(autouse=True)
def media_dir(tmpdir, settings):
tmp_dir = tmpdir.mkdir('actesweb').dirname
settings.MEDIA_ROOT = tmp_dir
yield tmp_dir
shutil.rmtree(tmp_dir, ignore_errors=True)
PAYLOAD = [
{
'birth': json.loads(get_file_from_test_base_dir('payload_birth.json'))
},
{
'mariage': json.loads(get_file_from_test_base_dir('payload_mariage.json'))
},
{
'death': json.loads(get_file_from_test_base_dir('payload_death.json'))
}
]
@pytest.fixture(params=PAYLOAD)
def payload(request):
return request.param
def get_demand_filepath(con, demand_id):
filename = '_'.join(demand_id.split('_')[1:])
return os.path.join(con.basepath, filename)
def assert_file_content_values(filename, expectations):
with io.open(filename, 'rb') as fp:
for line in fp.readlines():
field, value = line.split('=')
if field in expectations:
assert value.strip() == expectations[field]
def test_demand_creation(app, payload, actesweb):
url = '/actesweb/test/create/'
if 'birth' in payload:
response = app.post_json(url, params=payload['birth'])
demand_id = response.json['data']['demand_id']
demfile = get_demand_filepath(actesweb, demand_id)
assert_file_content_values(
demfile, dict(
DEMANDEUR_CIVILITE="Madame",
DEMANDEUR_NOM_USAGE="Whatever",
DEMANDEUR_PRENOMS="Kim Chelsea",
DEMANDEUR_ADRESSE1="37 Rue du Cheval Blanc",
DEMANDEUR_VILLE="Nancy",
DEMANDEUR_PAYS="France",
DEMANDEUR_TEL="+33 6 55 44 22 11",
DEMANDEUR_ADR="chelsea@whatever.com",
DEMANDE_NOM="Whatever",
DEMANDE_PRENOMS="Kevin",
DEMANDE_DATE_EVENEMENT="20120714",
TYPE_DEMANDE="Copie Integrale",
ACTE="NA",
NB="1",
LIEU_EVENEMENT="Nancy",
PERE_NOM="Smith",
PERE_PRENOMS="John Oliver",
MERE_NOM="Smith",
MERE_PRENOM="Kim",
DEMANDE_SEXE="m"
)
)
elif 'mariage' in payload:
response = app.post_json(url, params=payload['mariage'])
demand_id = response.json['data']['demand_id']
demfile = get_demand_filepath(actesweb, demand_id)
assert_file_content_values(
demfile, dict(
DEMANDEUR_CIVILITE="Madame",
DEMANDEUR_NOM_USAGE="Whatever",
DEMANDEUR_PRENOMS="Kim Chelsea",
DEMANDEUR_ADRESSE1="37 Rue du Cheval Blanc",
DEMANDEUR_VILLE="Nancy",
DEMANDEUR_PAYS="France",
DEMANDEUR_TEL="+33 6 55 44 22 11",
DEMANDEUR_ADR="chelsea@whatever.com",
DEMANDE_NOM="Whatever",
DEMANDE_PRENOMS="Kevin",
DEMANDE_DATE_EVENEMENT="20120714",
TYPE_DEMANDE="Copie Integrale",
ACTE="MA",
NB="1",
LIEU_EVENEMENT="Nancy",
PERE_NOM="Smith",
PERE_PRENOMS="John Oliver",
MERE_NOM="Smith",
MERE_PRENOM="Kim",
DEMANDE_SEXE="m",
CONJOINT_NOM="Contrao",
CONJOIN_PRENOMS="Chelsea",
CONJOINT_PERE_NOM="Scaramucci",
CONJOINT_PERE_PRENOMS="Antonio",
CONJOINT_MERE_NOM="Scaramucci",
CONJOINT_MERE_PRENOMS="Marguerite",
)
)
else:
response = app.post_json(url, params=payload['death'])
demand_id = response.json['data']['demand_id']
demfile = get_demand_filepath(actesweb, demand_id)
assert_file_content_values(
demfile, dict(
DEMANDEUR_CIVILITE="Madame",
DEMANDEUR_NOM_USAGE="Whatever",
DEMANDEUR_PRENOMS="Kim Chelsea",
DEMANDEUR_ADRESSE1="37 Rue du Cheval Blanc",
DEMANDEUR_VILLE="Nancy",
DEMANDEUR_PAYS="France",
DEMANDEUR_TEL="+33 6 55 44 22 11",
DEMANDEUR_ADR="chelsea@whatever.com",
DEMANDE_NOM="Whatever",
DEMANDE_PRENOMS="Kevin",
DEMANDE_DATE_EVENEMENT="20120714",
TYPE_DEMANDE="Extrait sans filiation",
ACTE="DE",
NB="1",
LIEU_EVENEMENT="Nancy",
DEMANDE_SEXE="m"
)
)