diff --git a/atreal_openads/json_schemas.py b/atreal_openads/json_schemas.py index ff1ad79..33049ed 100644 --- a/atreal_openads/json_schemas.py +++ b/atreal_openads/json_schemas.py @@ -144,7 +144,7 @@ JSON_SCHEMA_CREATE_DOSSIER_IN = { "terrain_code_postal", "terrain_localite", "reference_cadastrale", - "proprietaire", + #"proprietaire", "qualite", "nom", "prenom", diff --git a/atreal_openads/models.py b/atreal_openads/models.py index f2afafc..a3b3589 100644 --- a/atreal_openads/models.py +++ b/atreal_openads/models.py @@ -24,11 +24,12 @@ import base64 import datetime import json import os -import re import urlparse import magic +from urllib import quote + from django.db import models from django.http import Http404 from django.utils.translation import ugettext_lazy as _ @@ -162,6 +163,8 @@ class ForwardFile(models.Model, BaseModel): # pylint: disable=too-many-instance # @see: https://docs.djangoproject.com/en/2.2/topics/db/models/ # The note entitled "Overridden model methods are not called on bulk operations" def save(self, *args, **kwargs): # pylint: disable=arguments-differ + """Save the entity, overwritten to preprocessing data and validate model.""" + # delete file content (on success) if self.upload_status == 'success': # pylint: disable=no-member @@ -181,6 +184,8 @@ class ForwardFile(models.Model, BaseModel): # pylint: disable=too-many-instance # 'file_hash', 'orig_filename', 'upload_file' # because if they are all empty we dont have any usefull information about the upload def clean(self, *args, **kwargs): # pylint: disable=arguments-differ + """Check all the fields, overwritten to check grouped blank/null fields.""" + ret = super(ForwardFile, self).clean(*args, **kwargs) if (not self.file_hash and not self.orig_filename @@ -226,7 +231,7 @@ class Collectivite(models.Model, BaseModel): if fields: rels = [] for rel_name in ['forward_file', 'guichet']: - if (fields[0] and hasattr(fields[0], 'name') and fields[0].name == rel_name): + if fields[0] and hasattr(fields[0], 'name') and fields[0].name == rel_name: rels.append(fields.pop(0)) for rel in reversed(rels): fields.append(rel) @@ -510,7 +515,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } # } ) - # pylint: disable=unused-argument,arguments-differ,keyword-arg-before-vararg + # pylint: disable=unused-argument,arguments-differ def check_status(self, request=None, *args, **kwargs): """Check avaibility of the openADS.API service.""" url = urlparse.urljoin(self.openADS_API_url, '__api__') @@ -525,6 +530,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): example_pattern='{type_dossier}/', parameters={ 'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'}, + 'type_dossier_detaille': {'description': _("Detailled type of 'dossier'"), + 'example_value': 'CUb'}, 'collectivite': { 'description': _("Use this collectivite (instead of the default one)"), 'example_value': '3' @@ -537,7 +544,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): 'request_body': { 'schema': { 'application/json': JSON_SCHEMA_CREATE_DOSSIER_IN - } # pylint: disable=too-many-statements,too-many-branches,too-many-locals + } # pylint: disable=too-many-statements,too-many-branches,too-many-locals,too-many-arguments } # 'response_body': { # 'schema': { @@ -546,8 +553,9 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } } ) - # pylint: disable=unused-argument,keyword-arg-before-vararg - def create_dossier(self, request, type_dossier, collectivite=None, now=None, *args, **kwargs): + # pylint: disable=unused-argument + def create_dossier(self, request, type_dossier, type_dossier_detaille=None, collectivite=None, + now=None, *args, **kwargs): """Create an openADS 'dossier'.""" # loads the request body as JSON content @@ -571,7 +579,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): else: # the collectivite has a guichet - if (hasattr(collectivite, 'guichet') and collectivite.guichet): + if hasattr(collectivite, 'guichet') and collectivite.guichet: # get the datetime against which the 'guichet' is checked for opening now_fmt = '%Y-%m-%d %H:%M:%S' @@ -592,7 +600,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): return {'message': _(u"Guichet closed for collectivite '%s'" % collectivite)} # build the payload - payload = {"collectivite": int(collectivite_id)} + payload = { + "collectivite": int(collectivite_id), + #"type_detaille": type_dossier + } + + if type_dossier_detaille: + payload["type_detaille"] = type_dossier_detaille payload["terrain"] = { "numero_voie": normalize(json_data['fields']['terrain_numero_voie']), @@ -620,7 +634,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # setup demandeur variable prefix prefixes = {"demandeurs": ''} - if normalize(json_data['fields']['proprietaire']) != 'Oui': + if ('proprietaire' in json_data['fields'] and + normalize(json_data['fields']['proprietaire']) != 'Oui'): prefixes["mandataires"] = 'mandataire_' # for each type of demandeur with associated prefix @@ -679,7 +694,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): self.log_json_payload(payload) # every field key that might contain a file content - file_keys = ['cerfa'] + ['plan_cadastral_%s' % i for i in range(1, 5)] + ['pouvoir_mandat'] + file_keys = ['cerfa'] + ['annexe_%s' % i for i in range(1, 5)] # prepare files that will be forwarded files = [] @@ -688,6 +703,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): and json_data['fields'][k] and isinstance(json_data['fields'][k], dict) and 'content' in json_data['fields'][k]): + # get the content decoded from base 64 content = base64.b64decode(json_data['fields'][k]['content']) @@ -728,8 +744,18 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): elif '.' not in filename: filename += file_extension - # set the type fichier based on the key (less than 10 chars) - type_fichier = re.sub(r'_.*$', '', k)[:10] + # get the type fichier (less than 10 chars) + type_fichier = None + if k + '_type_raw' in json_data['fields']: + type_fichier = json_data['fields'][k + '_type_raw'] + if len(type_fichier) > 10: + raise APIError(u"Type '%s' for file '%s' is too long " + "(%d chars, but max is %d)" % ( + type_fichier, k, len(type_fichier), 10)) + elif k.lower() == 'cerfa': + type_fichier = 'CERFA' + else: + raise APIError(u"No type field/value for file '%s'" % k) # append the file to the list files.append({ @@ -742,11 +768,11 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # log files to be forwarded self.logger.debug("----- files (begining) -----") - self.logger.debug("%r", files) + self.logger.debug('%s', files) if files else self.logger.debug("(no files)") # pylint: disable=expression-not-assigned self.logger.debug("----- files (end) -----") # make a request to openADS.API (with the payload) - url = urlparse.urljoin(self.openADS_API_url, '/dossiers/%s' % type_dossier) + url = urlparse.urljoin(self.openADS_API_url, '/dossiers/%s' % quote(type_dossier)) response = self.requests.post( url, json=payload, @@ -863,13 +889,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } # } ) - # pylint: disable=unused-argument,keyword-arg-before-vararg + # pylint: disable=unused-argument def get_dossier(self, request, type_dossier, numero_dossier, *args, **kwargs): """Get informations about an openADS 'dossier'.""" # make a request to openADS.API - url = urlparse.urljoin(self.openADS_API_url, - '/dossier/%s/%s' % (type_dossier, numero_dossier)) + url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s' % ( + quote(type_dossier), quote(numero_dossier))) response = self.requests.get(url) # response is an error @@ -910,7 +936,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } # } ) - # pylint: disable=unused-argument,keyword-arg-before-vararg,no-self-use + # pylint: disable=unused-argument,no-self-use def get_fwd_files(self, request, numero_dossier, fichier_id=None, *args, **kwargs): """Get informations about the forwarding of user files to openADS.""" payload = [] @@ -973,7 +999,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } # } ) - # pylint: disable=unused-argument,keyword-arg-before-vararg + # pylint: disable=unused-argument def get_fwd_files_status(self, request, numero_dossier, fichier_id=None, *args, **kwargs): """Get informations about the forwarding of a user file to openADS.""" @@ -1006,7 +1032,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): @endpoint( perm='can_access', description=_("Get a 'courrier' from an openADS 'dossier'"), - pattern='^(?P\w+)/(?P\w+)/(?P\w+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string + pattern='^(?P\w+)/(?P\w+)/(?P[\w.,_ -]+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string example_pattern='{type_dossier}/{numero_dossier}/{lettre_type}', parameters={ 'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'}, @@ -1024,14 +1050,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } # } ) - # pylint: disable=unused-argument,keyword-arg-before-vararg + # pylint: disable=unused-argument def get_courrier(self, request, type_dossier, numero_dossier, lettre_type, *args, **kwargs): """Get a 'courrier' from an openADS 'dossier'.""" # make a request to openADS.API - url = urlparse.urljoin( - self.openADS_API_url, - '/dossier/%s/%s/courrier/%s' % (type_dossier, numero_dossier, lettre_type)) + url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s/courrier/%s' % ( + quote(type_dossier), quote(numero_dossier), quote(lettre_type))) response = self.requests.get(url) # response is an error @@ -1115,7 +1140,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # } ) # @raise ForwareFile.DoesNotExist if not found - # pylint: disable=unused-argument,keyword-arg-before-vararg + # pylint: disable=unused-argument def upload_user_files(self, request, type_dossier, numero_dossier, file_ids=None, *args, **kwargs): """A Job to forward user uploaded files to openADS.""" @@ -1198,8 +1223,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): self.log_json_payload(payload, 'payload') # make the request to openADS.API (with a specific timeout) - url = urlparse.urljoin(self.openADS_API_url, - '/dossier/%s/%s/files' % (type_dossier, numero_dossier)) + url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s/files' % ( + quote(type_dossier), quote(numero_dossier))) response = self.requests.post( url, json=payload, @@ -1294,3 +1319,67 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel): # return something to please pylint return True + + @endpoint( + perm='can_access', + description=_("Get the type of 'courrier' of an openADS 'dossier'"), + pattern='^(?P\w+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string + example_pattern='{type_dossier}/', + parameters={ + 'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'}, + 'type_dossier_detaille': {'description': _("Detailled type of 'dossier'"), + 'example_value': 'CUb'}, + 'specific': {'description': _("Get a specific version of the 'courrier type'"), + 'example_value': 'refus'}, + } # pylint: disable=too-many-branches + ) # pylint: disable=no-self-use + # pylint: disable=unused-argument + def get_courrier_type(self, request, type_dossier, type_dossier_detaille=None, specific=None, + *args, **kwargs): + """Get the type of 'courrier' for an openADS 'dossier'.""" + + courrier_type = None + + if type_dossier == 'DIA': + courrier_type = 'dia_renonciation_preempter' + if specific == 'delegation': + courrier_type = 'dia_delegation' + elif specific == 'irrecevabilite': + courrier_type = 'dia_irrecevabilite' + elif specific == 'preemption': + courrier_type = 'dia_souhait_preempter' + + elif type_dossier == 'CU': + courrier_type = 'CUa' + if type_dossier_detaille == 'CUb': + courrier_type = 'CUb - ACCORD' + if specific == 'refus': + courrier_type = 'CUb - REFUS' + + elif type_dossier == 'DP': + courrier_type = 'decision_non_opposition_DP' + if specific == 'annulation': + courrier_type = 'arrete_annulation_DP' + elif specific == 'prolongation': + courrier_type = 'arrete_prorogation_DP' + elif specific == 'prolongation_refus': + courrier_type = 'arrete_refus_prorogation_DP' + elif specific == 'transfert_refus': + courrier_type = 'arrete_refus_transfert_DP' + elif specific == 'transfert': + courrier_type = 'arrete_transfert_DP' + elif specific == 'attestation_tacite': + courrier_type = 'attestation_non opposition_tacite_DP' + elif specific == 'opposition': + courrier_type = 'decision_opposition_DP' + elif specific == 'certificat_tacite': + courrier_type = 'certificat_opposition_tacite_DP' + + elif type_dossier == 'PC' or type_dossier == 'PI': + courrier_type = 'arrete_ss_reserves' + if specific == 'refus': + courrier_type = 'arrete_refus' + + # TODO add others type and specifics variants + + return {'courrier_type': courrier_type} diff --git a/tests/test_atreal_openads.py b/tests/test_atreal_openads.py index 9ed4ac4..47d5813 100644 --- a/tests/test_atreal_openads.py +++ b/tests/test_atreal_openads.py @@ -432,21 +432,24 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ "field_id": "50", "filename": os.path.basename(fake_conf['TEST_FILE_CERFA_DIA']) }, - "plan_cadastral_1": { + "annexe_1_type_raw": "plan", + "annexe_1": { "content": get_file_data(fake_conf['TEST_FILE_PLAN_CADASTRAL']), "content_type": "application/pdf", "filename": os.path.basename(fake_conf['TEST_FILE_PLAN_CADASTRAL']) }, - "plan_cadastral_2": { + "annexe_2_type_raw": "plan", + "annexe_2": { "content": get_file_data(fake_conf['TEST_FILE_PLAN_CADASTRAL']), "content_type": "application/pdf", # "filename": 'plan_cad' }, - "pouvoir_mandat": { + "annexe_3_type_raw": "pouvoir", + "annexe_3": { "content": get_file_data(fake_conf['TEST_FILE_CERFA_DIA']), "content_type": "application/pdf", "filename": 'mandat' - } + }, } } request_1.method = 'POST' @@ -469,7 +472,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ with pytest.raises(APIError) as exception: with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp_bad - atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open) + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) assert unicode(exception.value) == "HTTP error: 502" # TODO update the code and return message when it will be @@ -484,7 +488,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ atreal_openads.create_dossier(request_1, 'DIA', collectivite=999) assert unicode(exception.value) == "HTTP error: 404" - jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now_closed) + jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_closed) assert jresp is not None assert len(jresp) == 1 assert 'message' in jresp @@ -492,8 +497,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ now_str_fmt = '%Y-%m-%d %H:%M:%S' now_closed_str = now_closed.strftime(now_str_fmt) - jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, - now_closed_str) + jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_closed_str) assert jresp is not None assert len(jresp) == 1 assert 'message' in jresp @@ -501,14 +506,42 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ now_invalid = {'invalid': 'type'} with pytest.raises(APIError) as exception: - jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, - now_invalid) + jresp = atreal_openads.create_dossier(request_1, 'DIA', + collectivite=collectivite_1.openADS_id, + now=now_invalid) assert unicode(exception.value) == ( u"Invalid value of type '%s' for now argument of endpoint '%s' (must be: %s)" % ( type(now_invalid), 'create_dossier', "datetime or string formatted to '%s'" % now_str_fmt)) + annexe_3_type_bak = fake_req_json['fields']['annexe_3_type_raw'] + fake_req_json['fields']['annexe_3_type_raw'] = 'toooooooooooo_looonnnngggggg' + request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access + with pytest.raises(APIError) as exception: + with mock.patch('passerelle.utils.Request.post') as requests_post: + requests_post.return_value = fake_resp_bad + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) + assert unicode(exception.value) == ( + u"Type '%s' for file '%s' is too long (%d chars, but max is %d)" % ( + fake_req_json['fields']['annexe_3_type_raw'], + 'annexe_3', + len(fake_req_json['fields']['annexe_3_type_raw']), + 10)) + + del fake_req_json['fields']['annexe_3_type_raw'] + request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access + with pytest.raises(APIError) as exception: + with mock.patch('passerelle.utils.Request.post') as requests_post: + requests_post.return_value = fake_resp_bad + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) + assert unicode(exception.value) == u"No type field/value for file '%s'" % 'annexe_3' + + fake_req_json['fields']['annexe_3_type_raw'] = annexe_3_type_bak + request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access + fake_resp_json = { 'numero_dossier': fake_conf['FAKE_NUMERO_DOSSIER'], 'files': [{ @@ -526,8 +559,9 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp - jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, - now=now_open) + jresp = atreal_openads.create_dossier(request_1, 'DIA', + collectivite=collectivite_1.openADS_id, + now=now_open, type_dossier_detaille='DIA') assert jresp['numero_dossier'] == fake_resp_json['numero_dossier'] assert jresp['recepisse']['b64_content'] == fake_resp_json['files'][0]['b64_content'] assert jresp['recepisse']['content_type'] == 'application/pdf' @@ -538,7 +572,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ with pytest.raises(APIError) as exception: with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp - atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open) + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) assert unicode(exception.value) == ( u"Expecting '%s' value in JSON response to be a %s (not a %s)" % ( 'numero_dossier', 'string', type({}))) @@ -548,7 +583,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ with pytest.raises(APIError) as exception: with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp - atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open) + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) assert unicode(exception.value) == u"Expecting 'numero_dossier' key in JSON response" fake_resp_json['files'][0]['b64_content'] = 'invalid_;{[content}' @@ -556,14 +592,16 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_ with pytest.raises(APIError) as exception: with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp - atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open) + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) assert unicode(exception.value) == u'Failed to decode recepisse content from base 64' fake_resp._content = 'df[{gfd;g#vfd' # pylint: disable=protected-access with pytest.raises(APIError) as exception: with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = fake_resp - atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open) + atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id, + now=now_open) # pylint: disable=protected-access assert unicode(exception.value) == u'No JSON content returned: %r' % fake_resp._content @@ -955,3 +993,79 @@ def test_upload_user_files(fake_conf, atreal_openads, request_1): assert ffup.upload_attempt == 3 assert ffup.upload_status == 'success' assert ffup.upload_msg == 'uploaded successfuly' + +# pylint: disable=unused-argument,redefined-outer-name +# pylint: disable=too-many-statements +def test_get_courrier_type(fake_conf, atreal_openads): + """Test the method AtrealOpenads.get_courrier_type().""" + + type_mapping = { + 'DIA': { + 'default': 'dia_renonciation_preempter', + 'detailled': [], + 'specifics': [ + ('delegation', 'dia_delegation'), + ('irrecevabilite', 'dia_irrecevabilite'), + ('preemption', 'dia_souhait_preempter')]}, + 'CU': { + 'default': 'CUa', + 'detailled': ['CUa', 'CUb'], + 'CUb': { + 'default': 'CUb - ACCORD', + 'specifics': [ + ('refus', 'CUb - REFUS')]}}, + 'DP': { + 'default': 'decision_non_opposition_DP', + 'detailled': [], + 'specifics': [ + ('annulation', 'arrete_annulation_DP'), + ('prolongation', 'arrete_prorogation_DP'), + ('prolongation_refus', 'arrete_refus_prorogation_DP'), + ('transfert_refus', 'arrete_refus_transfert_DP'), + ('transfert', 'arrete_transfert_DP'), + ('attestation_tacite', 'attestation_non opposition_tacite_DP'), + ('opposition', 'decision_opposition_DP'), + ('certificat_tacite', 'certificat_opposition_tacite_DP')]}, + 'PC': { + 'default': 'arrete_ss_reserves', + 'detailled': [], + 'specifics': [ + ('refus', 'arrete_refus')]}, + 'PI': { + 'default': 'arrete_ss_reserves', + 'detailled': [], + 'specifics': [ + ('refus', 'arrete_refus')]} + } + + # pylint: disable=too-many-nested-blocks + for type_dossier, infos in type_mapping.items(): + courrier_type = infos['default'] + types_detailles = infos['detailled'] if infos['detailled'] else [None] + for type_detaille in types_detailles: + if type_detaille: + if type_detaille in infos: + + if 'default' in infos[type_detaille]: + courrier_type = infos[type_detaille]['default'] + res = atreal_openads.get_courrier_type(None, type_dossier, + type_dossier_detaille=type_detaille) + assert res == {'courrier_type': courrier_type} + + if 'specifics' in infos[type_detaille]: + for specific_t in infos[type_detaille]['specifics']: + res = atreal_openads.get_courrier_type( + None, type_dossier, type_dossier_detaille=type_detaille, + specific=specific_t[0]) + assert res == {'courrier_type': specific_t[1]} + + elif 'specifics' in infos: + for specific_t in infos['specifics']: + res = atreal_openads.get_courrier_type(None, type_dossier, + type_dossier_detaille=type_detaille, + specific=specific_t[0]) + assert res == {'courrier_type': specific_t[1]} + + else: + res = atreal_openads.get_courrier_type(None, type_dossier) + assert res == {'courrier_type': courrier_type}