From dac361256b362975a2f4bad004e6c47269363147 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Fri, 13 Sep 2019 11:40:41 +0200
Subject: [PATCH] cartads cs: add endpoint to send a "DOC" (#36102)

---
 passerelle/apps/cartads_cs/models.py | 86 ++++++++++++++++++++++++++--
 tests/test_cartads_cs.py             | 57 ++++++++++++++++++
 2 files changed, 137 insertions(+), 6 deletions(-)

diff --git a/passerelle/apps/cartads_cs/models.py b/passerelle/apps/cartads_cs/models.py
index 55fffb08..a1524256 100644
--- a/passerelle/apps/cartads_cs/models.py
+++ b/passerelle/apps/cartads_cs/models.py
@@ -46,12 +46,17 @@ import zeep.helpers as zeep_helpers
 
 from passerelle.base.models import BaseResource
 from passerelle.utils.api import endpoint
+from passerelle.utils.jsonresponse import APIError
 
 
 def cartads_file_location(instance, filename):
     return 'cartads_cs/%s/%s' % (instance.tracking_code, filename)
 
 
+def key_value_of_stringstring(d):
+    return {'KeyValueOfstringstring': [{'Key': x, 'Value': y} for x, y in d.items()]}
+
+
 class CartaDSDataCache(models.Model):
     data_type = models.CharField(max_length=50)
     data_parameters = JSONField(default={})
@@ -484,6 +489,40 @@ class AbstractCartaDSCS(BaseResource):
             piece['files'].append({'url': upload_url})
         return {'data': pieces}
 
+    @endpoint(perm='can_access',
+              description=_('Get list of DOC file items'),
+              parameters={
+                  'tracking_code': TRACKING_CODE_PARAM,
+              })
+    def doc_pieces(self, request, tracking_code):
+        dossier = CartaDSDossier.objects.get(tracking_code=tracking_code)
+        status = self.status(request, dossier.id)
+        if status['status_label'] != 'Attente DOC':
+            raise APIError('wrong status')
+
+        signer = Signer(salt='cart@ds_cs')
+        upload_token = signer.sign(tracking_code)
+        pieces = [
+            {'id': 'cerfa-doc',
+             'text': 'CERFA',
+             'description': '',
+             'codePiece': '',
+             'reglementaire': True,
+             'files': [],
+             'max_files': 1,
+            },
+        ]
+        for piece in pieces:
+            if request:
+                upload_url = request.build_absolute_uri('%supload/%s/%s/' % (
+                    self.get_absolute_url(),
+                    piece['id'],
+                    upload_token))
+            else:
+                upload_url = None
+            piece['files'].append({'url': upload_url})
+        return {'data': pieces}
+
     @endpoint(methods=['post'],
               pattern='^(?P<id_piece>[\w-]+)/(?P<token>[\w:_-]+)/$',
               description=_('Upload a single document file'),
@@ -615,9 +654,6 @@ class AbstractCartaDSCS(BaseResource):
         zip_filename = os.path.join(default_storage.path('cartads_cs'), '%s.zip' % dossier.tracking_code)
         self.upload_zip(zip_filename)
 
-        def key_value_of_stringstring(d):
-            return {'KeyValueOfstringstring': [{'Key': x, 'Value': y} for x, y in d.items()]}
-
         client = self.soap_client()
         resp = client.service.NotifierDepotDossier(
                 self.get_token(),
@@ -675,9 +711,6 @@ class AbstractCartaDSCS(BaseResource):
              'codePiece': x['CodePiece'],
             } for x in resp]
 
-        def key_value_of_stringstring(d):
-            return {'KeyValueOfstringstring': [{'Key': x, 'Value': y} for x, y in d.items()]}
-
         client = self.soap_client(wsdl_url=self.get_wsdl_url('ServiceDocumentation'))
 
         for piece_type in pieces:
@@ -711,6 +744,47 @@ class AbstractCartaDSCS(BaseResource):
                     piece.sent_to_cartads = now()
                     piece.save()
 
+    @endpoint(perm='can_access',
+              description=_('Send DOC file items'),
+              parameters={
+                  'tracking_code': TRACKING_CODE_PARAM,
+              })
+    def send_doc_pieces(self, request, tracking_code):
+        dossier = CartaDSDossier.objects.get(tracking_code=tracking_code)
+        self.add_job('send_doc_pieces_to_cartads', dossier_id=dossier.id)
+        return {'err': 0, 'dossier_id': dossier.id}
+
+    def send_doc_pieces_to_cartads(self, dossier_id):
+        dossier = CartaDSDossier.objects.get(id=dossier_id)
+        client = self.soap_client(wsdl_url=self.get_wsdl_url('ServiceDocumentation'))
+        pieces = CartaDSFile.objects.filter(
+                    tracking_code=dossier.tracking_code,
+                    id_piece='cerfa-doc',
+                    sent_to_cartads__isnull=True)
+        assert pieces.count() == 1
+        piece = pieces[0]
+
+        content = piece.uploaded_file.read()
+        try:
+            resp = client.service.UploadFile(FileByteStream=content,
+                    _soapheaders={
+                        'IdDossier': dossier.cartads_id_dossier,
+                        'NomFichier': 'cerfa-doc.pdf',
+                        'Length': piece.uploaded_file.size,
+                        'Token': self.get_token(),
+                        'InformationsComplementaires': key_value_of_stringstring(
+                            {'docDaact': 'doc',
+                             'renameFile': True
+                            },
+                        ),
+            })
+        except zeep.exceptions.Fault as e:
+            self.logger.exception('error pushing file item %d (%r)', piece.id, e.message)
+        else:
+            assert resp is None
+            piece.sent_to_cartads = now()
+            piece.save()
+
     @endpoint(perm='can_access',
               description=_('Get status of file'),
               parameters={
diff --git a/tests/test_cartads_cs.py b/tests/test_cartads_cs.py
index 960ac3e8..e3c5a173 100644
--- a/tests/test_cartads_cs.py
+++ b/tests/test_cartads_cs.py
@@ -74,6 +74,21 @@ class FakeService():
         return 'True'
 
     def GetEtapesDossier(self, token, dossier_id, infos):
+        try:
+            dossier = CartaDSDossier.objects.get(cartads_id_dossier=dossier_id)
+        except CartaDSDossier.DoesNotExist:
+            dossier = None
+        if dossier and dossier.tracking_code == 'DOCXXXX':
+            return [{
+                'LibelleEtape': 'Attente DOC',
+                'IdEtapeDossier': 2356473L,
+                'DateEcheance': '2022-04-01T00:00:00',
+                'IdEtape': 12L,
+                'DateRealisation': None,
+                'DateReference': '2019-03-25T00:00:00',
+                'IdDossier': 471160L},]
+
+        # default
         return [{
             'DateEcheance': datetime.datetime(2019, 3, 1, 0, 0),
             'DateRealisation': None,
@@ -381,3 +396,45 @@ def test_additional_pieces_management(connector, app, cached_data):
 
     assert CartaDSFile.objects.filter(tracking_code=dossier.tracking_code,
             sent_to_cartads=None).count() == 0
+
+
+def test_doc_pieces_management(connector, app, cached_data):
+    CartaDSDossier.objects.all().delete()
+    test_send(connector, app, cached_data)
+    dossier = CartaDSDossier.objects.all()[0]
+
+    with mock.patch('passerelle.apps.cartads_cs.models.CartaDSCS.soap_client') as client:
+        client.return_value = mock.Mock(service=FakeService())
+        resp = app.get('/cartads-cs/test/doc_pieces?tracking_code=%s' % dossier.tracking_code)
+        assert resp.json['err']
+
+    dossier.tracking_code = 'DOCXXXX'  # to get the right status
+    dossier.save()
+    with mock.patch('passerelle.apps.cartads_cs.models.CartaDSCS.soap_client') as client:
+        client.return_value = mock.Mock(service=FakeService())
+        resp = app.get('/cartads-cs/test/doc_pieces?tracking_code=%s' % dossier.tracking_code)
+    data = resp.json['data']
+    assert len(data) == 1
+    assert data[0]['text'] == 'CERFA'
+    assert data[0]['max_files'] == 1
+    assert len(data[0]['files']) == 1
+    assert data[0]['files'][0].keys() == ['url']
+
+    pdf_contents = open(os.path.join(os.path.dirname(__file__), 'data', 'pdf-form.pdf')).read()
+    resp = app.post(data[0]['files'][0]['url'],
+                    upload_files=[('files[]', 'test.pdf', pdf_contents)])
+    assert resp.json[0]['token']
+    assert CartaDSFile.objects.filter(tracking_code=dossier.tracking_code,
+            sent_to_cartads=None).count() == 1
+
+    Job.objects.all().delete()
+    resp = app.get('/cartads-cs/test/send_doc_pieces?tracking_code=%s' % dossier.tracking_code)
+    assert Job.objects.all().count() == 1
+
+    with mock.patch('passerelle.apps.cartads_cs.models.CartaDSCS.soap_client') as client:
+        client.return_value = mock.Mock(service=FakeService())
+        connector.jobs()
+        assert Job.objects.filter(method_name='send_doc_pieces_to_cartads', status='completed').count()
+
+    assert CartaDSFile.objects.filter(tracking_code=dossier.tracking_code,
+            sent_to_cartads=None).count() == 0
-- 
2.23.0

