From b04103ff1edc0edce5f122857cf9cc4dd8340ba8 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 14:58:26 +0200
Subject: [PATCH] cartads_cs: add endpoint to send DAACT items (#36112)

---
 passerelle/apps/cartads_cs/models.py | 97 ++++++++++++++++++++++++++++
 tests/test_cartads_cs.py             | 83 ++++++++++++++++++++++++
 2 files changed, 180 insertions(+)

diff --git a/passerelle/apps/cartads_cs/models.py b/passerelle/apps/cartads_cs/models.py
index b285c2a6..1c1dbc0f 100644
--- a/passerelle/apps/cartads_cs/models.py
+++ b/passerelle/apps/cartads_cs/models.py
@@ -34,6 +34,7 @@ from django.core.files.storage import default_storage
 from django.core.signing import Signer
 from django.core.urlresolvers import reverse
 from django.db import models
+from django.db.models import Q
 from django.http import HttpResponse
 from django.utils.encoding import force_text
 from django.utils.timezone import now
@@ -526,6 +527,55 @@ class AbstractCartaDSCS(BaseResource):
             piece['files'].append({'url': upload_url})
         return {'data': pieces}
 
+    @endpoint(perm='can_access',
+              description=_('Get list of DAACT file items'),
+              parameters={
+                  'tracking_code': TRACKING_CODE_PARAM,
+              })
+    def daact_pieces(self, request, tracking_code):
+        dossier = CartaDSDossier.objects.get(tracking_code=tracking_code)
+        status = self.status(request, dossier.id)
+        if status['status_label'] != 'Attente DAACT':
+            raise APIError('wrong status')
+
+        client = self.soap_client(wsdl_url=self.get_wsdl_url('ServicePiece'))
+        resp = client.service.GetPiecesDaact(self.get_token(), dossier.cartads_id_dossier)
+
+        signer = Signer(salt='cart@ds_cs')
+        upload_token = signer.sign(tracking_code)
+
+        pieces = [
+            {'id': 'cerfa-daact',
+             'text': 'CERFA',
+             'description': '',
+             'codePiece': '',
+             'reglementaire': True,
+             'files': [],
+             'max_files': 1,
+            },
+        ]
+
+        pieces.extend([
+            {'id': 'daact-%s' % x['IdPiece'],
+             'text': x['LibellePiece'],
+             'description': x['Descriptif'],
+             'codePiece': x['CodePiece'],
+             'files': [],
+             'max_files': 6,
+             } for x in resp])
+
+        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'] = []
+            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'),
@@ -789,6 +839,53 @@ class AbstractCartaDSCS(BaseResource):
             piece.sent_to_cartads = now()
             piece.save()
 
+    @endpoint(perm='can_access',
+              description=_('Send DAACT file items'),
+              parameters={
+                  'tracking_code': TRACKING_CODE_PARAM,
+              })
+    def send_daact_pieces(self, request, tracking_code):
+        dossier = CartaDSDossier.objects.get(tracking_code=tracking_code)
+        self.add_job('send_daact_pieces_to_cartads', dossier_id=dossier.id)
+        return {'err': 0, 'dossier_id': dossier.id}
+
+    def send_daact_pieces_to_cartads(self, dossier_id):
+        dossier = CartaDSDossier.objects.get(id=dossier_id)
+        pieces = self.daact_pieces(None, dossier.tracking_code)['data']
+
+        client = self.soap_client(wsdl_url=self.get_wsdl_url('ServiceDocumentation'))
+        for piece_type in pieces:
+            for piece in CartaDSFile.objects.filter(
+                    tracking_code=dossier.tracking_code,
+                    sent_to_cartads__isnull=True,
+                    id_piece=piece_type['id']):
+                content = piece.uploaded_file.read()
+                try:
+                    infos = {
+                        'renameFile': True,
+                    }
+                    if piece.id_piece == 'cerfa-daact':
+                        infos['docDaact'] = 'daact'
+                        filename = 'cerfa-daact.pdf'
+                    else:
+                        infos['docDaact'] = 'pieceDaact'
+                        infos['idPieceDaact'] = piece.id_piece.split('-', 1)[-1]
+                        filename = '%s%s' % (piece_type['codePiece'], os.path.splitext(piece.uploaded_file.name)[-1])
+                    resp = client.service.UploadFile(FileByteStream=content,
+                            _soapheaders={
+                                'IdDossier': dossier.cartads_id_dossier,
+                                'NomFichier': filename,
+                                'Length': piece.uploaded_file.size,
+                                'Token': self.get_token(),
+                                'InformationsComplementaires': key_value_of_stringstring(infos)
+                    })
+                except zeep.exceptions.Fault as e:
+                    self.logger.exception('error pushing daact 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 e3c5a173..9d9f0118 100644
--- a/tests/test_cartads_cs.py
+++ b/tests/test_cartads_cs.py
@@ -87,6 +87,15 @@ class FakeService():
                 'DateRealisation': None,
                 'DateReference': '2019-03-25T00:00:00',
                 'IdDossier': 471160L},]
+        elif dossier and dossier.tracking_code == 'DAACTXXXX':
+            return [{
+                'LibelleEtape': 'Attente DAACT',
+                'IdEtapeDossier': 2356473L,
+                'DateEcheance': '2022-04-01T00:00:00',
+                'IdEtape': 12L,
+                'DateRealisation': None,
+                'DateReference': '2019-03-25T00:00:00',
+                'IdDossier': 471160L},]
 
         # default
         return [{
@@ -123,6 +132,30 @@ class FakeService():
                 (u'NbDocuments', 0L)]),
         ]
 
+    def GetPiecesDaact(self, token, dossier_id):
+        return [
+            OrderedDict([
+                (u'CodePiece', 'AT1'),
+                (u'DateDemande', None),
+                (u'DatePresentation', None),
+                (u'DateReception', None),
+                (u'Descriptif', u"L'attestation constatant..."),
+                (u'IdDosPiece', 0L),
+                (u'IdPiece', 191L),
+                (u'LibellePiece', 'Attestation constat des travaux'),
+                (u'NbDocuments', 0L)]),
+            OrderedDict([
+                (u'CodePiece', 'AT2'),
+                (u'DateDemande', None),
+                (u'DatePresentation', None),
+                (u'DateReception', None),
+                (u'Descriptif', u"Dans les cas..."),
+                (u'IdDosPiece', 0L),
+                (u'IdPiece', 192L),
+                (u'LibellePiece', u'Document du...'),
+                (u'NbDocuments', 0L)]),
+        ]
+
     def UploadFile(self, FileByteStream, _soapheaders):
         assert FileByteStream
         assert _soapheaders
@@ -438,3 +471,53 @@ def test_doc_pieces_management(connector, app, cached_data):
 
     assert CartaDSFile.objects.filter(tracking_code=dossier.tracking_code,
             sent_to_cartads=None).count() == 0
+
+
+def test_daact_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/daact_pieces?tracking_code=%s' % dossier.tracking_code)
+        assert resp.json['err']
+
+    dossier.tracking_code = 'DAACTXXXX'  # 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/daact_pieces?tracking_code=%s' % dossier.tracking_code)
+    data = resp.json['data']
+    assert len(data) == 3
+    assert data[0]['text'] == 'CERFA'
+    assert data[0]['max_files'] == 1
+    for piece in data:
+        assert len(piece['files']) == 1
+        assert piece['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
+
+    pdf_contents = open(os.path.join(os.path.dirname(__file__), 'data', 'pdf-form.pdf')).read()
+    resp = app.post(data[1]['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() == 2
+
+    Job.objects.all().delete()
+    resp = app.get('/cartads-cs/test/send_daact_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_daact_pieces_to_cartads', status='completed').count()
+
+    assert CartaDSFile.objects.filter(tracking_code=dossier.tracking_code,
+            sent_to_cartads=None).count() == 0
-- 
2.23.0

