From bc6d9c89281bcb50345cf4d49b55da8eae659c3e Mon Sep 17 00:00:00 2001 From: Josue Kouka Date: Tue, 13 Jun 2017 18:51:17 +0200 Subject: [PATCH 1/2] add civil status common api (#16768) --- passerelle/civilstatus/__init__.py | 62 ++++++++++++++++++++++++++++++++ passerelle/contrib/mdel/models.py | 3 +- tests/test_civilstatus.py | 73 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 passerelle/civilstatus/__init__.py create mode 100644 tests/test_civilstatus.py diff --git a/passerelle/civilstatus/__init__.py b/passerelle/civilstatus/__init__.py new file mode 100644 index 0000000..60753aa --- /dev/null +++ b/passerelle/civilstatus/__init__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Passerelle - uniform access to data and services +# Copyright (C) 2017 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 . +import json + +from django.utils.translation import ugettext_lazy as _ + +from passerelle.utils.api import endpoint +from passerelle.utils.jsonresponse import APIError + + +# Dict of mandatory keys and their expected values + +MANDATORY_DATA = { + 'application_id': None, + 'application_time': None, + 'certificate_type': ('birth', 'mariage', 'death', 'other'), + 'document_type': ('full', 'multilingual', 'with-filiation', 'without-filiation'), + 'applicant_lastname': None, + 'applicant_firstnames': None, + 'concerned_lastname': None, + 'concerned_firstnames': None, +} + + +class CivilStatusMixin(object): + + category = _('Civil Status') + + def create_demand(self, formdata, *args, **kwargs): + raise NotImplementedError + + def get_status(self, demand_id, **kwargs): + raise NotImplementedError + + @endpoint(perm='can_access', methods=['post']) + def create(self, request, *args, **kwargs): + payload = json.loads(request.body) + for key, values in MANDATORY_DATA.iteritems(): + if (key not in payload): + raise APIError('<%s> is required.' % key) + if values and payload[key] not in values: + raise APIError('<%s> value must be one of %s' % (key, values)) + + return self.create_demand(request, payload, *args, **kwargs) + + @endpoint(perm='can_access', methods=['get']) + def status(self, request, demand_id, **kwargs): + return self.get_status(demand_id) diff --git a/passerelle/contrib/mdel/models.py b/passerelle/contrib/mdel/models.py index c3f00c7..ae095ee 100644 --- a/passerelle/contrib/mdel/models.py +++ b/passerelle/contrib/mdel/models.py @@ -23,6 +23,7 @@ from dateutil.parser import parse as dateutil_parse from django.db import models from django.utils.translation import ugettext_lazy as _ +from passerelle.civilstatus import CivilStatusMixin from passerelle.base.models import BaseResource from passerelle.utils.api import endpoint from passerelle.utils.jsonresponse import APIError @@ -67,7 +68,7 @@ CERTIFICATE_TYPES = [ {'id': 'EXTRAIT-PLURILINGUE', 'text': 'Extrait plurilingue'}] -class MDEL(BaseResource): +class MDEL(CivilStatusMixin, BaseResource): """Connector converting Publik's Demand into MDEL (XML based format) Demand. It's able to manage demand such as : diff --git a/tests/test_civilstatus.py b/tests/test_civilstatus.py new file mode 100644 index 0000000..3170a29 --- /dev/null +++ b/tests/test_civilstatus.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +import json +import mock +import pytest + +from passerelle.civilstatus import CivilStatusMixin, MANDATORY_DATA +from passerelle.utils.jsonresponse import APIError + +from django.test import RequestFactory + + +C_DEMAND = {'demand_id': '123-NAIS-0'} +S_DEMAND = {'closed': True, 'status': 'rejected'} + + +def build_post_request(data): + request = RequestFactory() + return request.post('/', content_type='application/json', + data=json.dumps(data)) + + +@pytest.fixture +def base_payload(): + return { + "application_id": "123", + "application_time": "2017-06-11T10:30:25", + "certificate_type_label": "Acte de Naissance", + "certificate_type": "birth", + "document_type_label": "Copie Intégrale", + "document_type": "full", + "applicant_firstnames": "Johhny Jumper", + "applicant_lastname": "Doe", + "concerned_firstnames": "Johnny Jumper", + "concerned_lastname": "Dalton", + "concerned_birthdate": "1980-07-07", + "concerned_birthcity": "Nantes", + "concerned_birthcountry": "France", + } + + +@pytest.fixture(params=MANDATORY_DATA) +def case(request, base_payload): + base_payload.pop(request.param) + return request.param, base_payload + + +def test_civilstatus_mixin_missing_keys(app, case): + missing_key, payload = case + mixin = CivilStatusMixin() + with pytest.raises(APIError) as exc: + mixin.create(build_post_request(payload)) + + assert exc.value.message == '<%s> is required.' % missing_key + + +@mock.patch('passerelle.civilstatus.CivilStatusMixin.create_demand', + side_effect=lambda x: C_DEMAND) +@mock.patch('passerelle.civilstatus.CivilStatusMixin.get_status', + side_effect=lambda x: S_DEMAND) +def test_civilstatus_mixin_expected_keys(mock_cvs_status, mock_cvs_create, app, base_payload): + base_payload['certificate_type'] = 'whatever' + mixin = CivilStatusMixin() + with pytest.raises(APIError) as exc: + mixin.create(build_post_request(base_payload)) + + assert exc.value.message == " value must be one of ('birth', 'mariage', 'death', 'other')" + base_payload['certificate_type'] = 'birth' + request = build_post_request(base_payload) + resp_json = mixin.create(request) + assert resp_json['demand_id'] == '123-NAIS-0' + resp_json = mixin.status(request, '123-NAIS-0') + assert resp_json['status'] == 'rejected' + assert resp_json['closed'] is True -- 2.11.0