From 542c74ccb40c0bef3a2d1a09d7cbbdf6d667534b Mon Sep 17 00:00:00 2001
From: Emmanuel Cazenave <ecazenave@entrouvert.com>
Date: Mon, 21 Oct 2019 18:15:55 +0200
Subject: [PATCH 2/3] mdel: control zipfile structure (#36870)

---
 passerelle/apps/mdel/models.py |  8 ++++++--
 passerelle/apps/mdel/utils.py  | 19 +++++++++++++++----
 tests/test_mdel.py             | 27 ++++++++++++++++++++++++---
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/passerelle/apps/mdel/models.py b/passerelle/apps/mdel/models.py
index 0e54649a..b476d759 100644
--- a/passerelle/apps/mdel/models.py
+++ b/passerelle/apps/mdel/models.py
@@ -198,7 +198,7 @@ class Demand(models.Model):
 
         inputs_dir = os.path.join(resource_base_dir, self.resource.slug,
                                   'inputs', self.name)
-
+        input_files = {}
         attached_files = []
 
         if flow_type == 'ILE-LA':
@@ -245,6 +245,7 @@ class Demand(models.Model):
 
             doc = mdel.ILEData(self.demand_id, formdata)
             doc.save(inputs_dir)
+            input_files['demande'] = doc.filename
 
             for attached_file in attached_files:
                 attached_file.save(inputs_dir)
@@ -319,18 +320,21 @@ class Demand(models.Model):
 
             doc = mdel.AECData(self.demand_id, formdata)
             doc.save(inputs_dir)
+            input_files['demande'] = doc.filename
 
         submission_date = formdata.get('receipt_time', None)
 
         message = mdel.Message(flow_type, demand_num, code_insee, date=submission_date)
         message.save(inputs_dir)
+        input_files['message'] = message.filename
 
         description = mdel.Description(flow_type, demand_num, code_insee, date=submission_date,
                                        attached_files=attached_files)
         description.save(inputs_dir)
+        input_files['enveloppe'] = description.filename
 
         # create zip file
-        return zipdir(inputs_dir)
+        return zipdir(inputs_dir, input_files)
 
     def get_status(self):
         """Read demand' statuses from file
diff --git a/passerelle/apps/mdel/utils.py b/passerelle/apps/mdel/utils.py
index 4ec486b3..7de7d552 100644
--- a/passerelle/apps/mdel/utils.py
+++ b/passerelle/apps/mdel/utils.py
@@ -69,15 +69,26 @@ class ElementFactory(etree.Element):
         return self
 
 
-def zipdir(path):
+def zipdir(path, input_files):
     """Zip directory
     """
+    basefiles = []
+    for key in ('message', 'enveloppe', 'demande'):
+        if key in input_files:
+            basefiles.append(input_files[key])
+
     archname = path + '.zip'
     with zipfile.ZipFile(archname, 'w', zipfile.ZIP_DEFLATED) as zipf:
-        for root, dirs, files in os.walk(path):
-            for f in files:
-                fpath = os.path.join(root, f)
+        for file_ in basefiles:
+            fpath = os.path.join(path, file_)
+            if os.path.exists(fpath):
+                zipf.write(fpath, file_)
+
+        for file_ in os.listdir(path):
+            if file_ not in basefiles:
+                fpath = os.path.join(path, file_)
                 zipf.write(fpath, os.path.basename(fpath))
+
     return archname
 
 
diff --git a/tests/test_mdel.py b/tests/test_mdel.py
index 7ecb9228..82fc8699 100644
--- a/tests/test_mdel.py
+++ b/tests/test_mdel.py
@@ -21,6 +21,7 @@ import os
 import json
 import base64
 import copy
+import zipfile
 
 from xml.etree import ElementTree as etree
 from lxml import etree as letree
@@ -55,6 +56,12 @@ def validate_schema(doc, xsd):
     letree.parse(doc, parser=parser)  # Will raise an exception if schema not respected
 
 
+def check_zip_file(zipdir, expected_files):
+    # check files order in zip
+    zipres = zipfile.ZipFile(zipdir, 'r')
+    files = [f.filename for f in zipres.infolist()]
+    assert files[:len(expected_files)] == expected_files
+
 
 @pytest.fixture
 def setup(db):
@@ -136,8 +143,12 @@ def test_create_aec_demand_type(app, setup, aec_payload):
     if aec_payload['display_id'] == '15-4':
         assert resp.json['data']['demand_id'] == '15-4-AEC-LA'
 
-        doc = os.path.join(get_resource_base_dir(), 'test', 'inputs', '15-4-AEC-LA--0', '15-4-AEC-LA-doc-.xml')
+        basedir = os.path.join(get_resource_base_dir(), 'test', 'inputs', '15-4-AEC-LA--0')
+        doc = os.path.join(basedir, '15-4-AEC-LA-doc-.xml')
         validate_schema(doc, AEC_XSD)
+        check_zip_file(
+            basedir + '.zip', ['message.xml', '15-4-AEC-LA-ent-.xml', '15-4-AEC-LA-doc-.xml']
+        )
 
         root = etree.parse(doc).getroot()
 
@@ -184,7 +195,12 @@ def test_create_aec_demand_type(app, setup, aec_payload):
 
         assert resp.json['data']['demand_id'] == '16-1-AEC-LA'
 
-        doc = os.path.join(get_resource_base_dir(), 'test', 'inputs', '16-1-AEC-LA--0', '16-1-AEC-LA-doc-.xml')
+        basedir = os.path.join(get_resource_base_dir(), 'test', 'inputs', '16-1-AEC-LA--0')
+        doc = os.path.join(basedir, '16-1-AEC-LA-doc-.xml')
+        validate_schema(doc, AEC_XSD)
+        check_zip_file(
+            basedir + '.zip', ['message.xml', '16-1-AEC-LA-ent-.xml', '16-1-AEC-LA-doc-.xml']
+        )
         validate_schema(doc, AEC_XSD)
 
         root = etree.parse(doc).getroot()
@@ -238,7 +254,12 @@ def test_create_aec_demand_type(app, setup, aec_payload):
     else:
         assert resp.json['data']['demand_id'] == '17-1-AEC-LA'
 
-        doc = os.path.join(get_resource_base_dir(), 'test', 'inputs', '17-1-AEC-LA--0', '17-1-AEC-LA-doc-.xml')
+        basedir = os.path.join(get_resource_base_dir(), 'test', 'inputs', '17-1-AEC-LA--0')
+        doc = os.path.join(basedir, '17-1-AEC-LA-doc-.xml')
+        validate_schema(doc, AEC_XSD)
+        check_zip_file(
+            basedir + '.zip', ['message.xml', '17-1-AEC-LA-ent-.xml', '17-1-AEC-LA-doc-.xml']
+        )
         validate_schema(doc, AEC_XSD)
 
         root = etree.parse(doc).getroot()
-- 
2.20.1

