This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
passerelle-grandlyon-cartads/cartads/models.py

603 lines
32 KiB
Python

# coding: utf8
# Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
import base64
import json
import datetime
import uuid
import zipfile
import StringIO
import HTMLParser
import os # TODO: inutile si on genere le zip in-memory
import tempfile # TODO: inutile si on genere le zip in-memory
from email import encoders
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from suds.client import Client
from suds.transport import Reply
from suds.transport.http import HttpAuthenticated
import suds.sudsobject
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache
from passerelle.base.models import BaseResource
from passerelle.utils.api import endpoint
from .formdata import FormData, CREATION_SCHEMA, list_schema_fields
class ParameterTypeError(Exception):
http_status = 400
log_error = False
def fill_sudsobject_with_dict(sudsobject, fields, prefix=None):
for key, value in sudsobject:
if prefix:
attr = '%s_%s' % (prefix, key)
else:
attr = key
if isinstance(value, suds.sudsobject.Object):
fill_sudsobject_with_dict(value, fields, attr)
else:
if attr in fields:
# sudsobject.foo.bar <- fields['foo_bar']
setattr(sudsobject, key, fields[attr])
def sudsobject_to_dict(sudsobject):
out = {}
for key, value in suds.sudsobject.asdict(sudsobject).iteritems():
if hasattr(value, '__keylist__'):
out[key] = sudsobject_to_dict(value)
elif isinstance(value, list):
out[key] = []
for item in value:
if hasattr(item, '__keylist__'):
out[key].append(sudsobject_to_dict(item))
else:
out[key].append(item)
else:
out[key] = value
return out
class CartADS(BaseResource):
token_url = models.URLField(_('Token URL'), max_length=256)
token_authorization = models.CharField(_('Token Authorization'), max_length=128)
wsdl_ads_dir_url = models.CharField(_('WSDL ADS Dir URL'), max_length=256) # not URLField, it can be file://
sendfile_ws_url = models.CharField(_('sendfile ws url'), max_length=256) # not URLField, it can be file://
cle_token_gfi = models.CharField(_('Cle Token GFI'), max_length=128)
verify_cert = models.BooleanField(default=True,
verbose_name=_('Check HTTPS Certificate validity'))
# TODO : a mettre en param du connecteur
#dirname = 'D:\LSM\Gfi\DepotDossierFTP\client1\\' #dev cartads
dirname = 'E:\LSM\Gfi\DepotDossierFTP\client1\\' #recette cartads
category = _('Business Process Connectors')
class Meta:
verbose_name = _('CartADS Webservices')
def get_token(self, renew=False):
cache_key = 'cartads-%s-token' % self.id
if not renew:
token = cache.get(cache_key)
if token:
return token
headers = {'Authorization': 'Basic %s' % self.token_authorization}
resp = self.requests.post(self.token_url, headers=headers,
data={'grant_type': 'client_credentials'},
verify=self.verify_cert).json()
token = '%s %s' % (resp.get('token_type'), resp.get('access_token'))
timeout = int(resp.get('expires_in'))
cache.set(cache_key, token, timeout)
self.logger.debug('new token: %s (timeout %ss)', token, timeout)
return token
def get_client(self, wsdl_file, attachments=[]):
class Transport(HttpAuthenticated):
def __init__(self, instance, attachments):
self.instance = instance
self.attachments = attachments
HttpAuthenticated.__init__(self)
def send(self, request):
request.message = request.message.replace("contentType", "xm:contentType")
request.headers['Authorization'] = self.instance.get_token()
#inutile pour test avec traitement dans la minute toujours active en dev et rec
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "message: ", request.message
'''
if u"<ns0:informationsComplementaires></ns0:informationsComplementaires>" in request.message:
# fait planter
#request.message = request.message.replace('xmlns:ns0="http://tempuri.org/"',
#'xmlns:ns0="http://tempuri.org/" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays')
request.message = request.message.replace(u"<ns0:informationsComplementaires></ns0:informationsComplementaires>",
u"<ns0:informationsComplementaires><arr:KeyValueOfstringstring><arr:Key>traitementImmediat</arr:Key><arr:Value>1</arr:Value></arr:KeyValueOfstringstring></ns0:informationsComplementaires>")
'''
resp = self.instance.requests.post(request.url, data=request.message,
headers=request.headers,
verify=self.instance.verify_cert)
if resp.status_code == 401:
# ask for a new token, and retry
request.headers['Authorization'] = self.instance.get_token(renew=True)
resp = self.instance.requests.post(request.url, data=request.message,
headers=request.headers,
verify=self.instance.verify_cert)
return Reply(resp.status_code, resp.headers, resp.content)
return Client(url=self.wsdl_ads_dir_url+wsdl_file, transport=Transport(self, attachments))
@endpoint(perm='can_access', methods=['get','post'])
def create(self, request):
# Create the in-memory file-like object for working w/imz (https://stackoverflow.com/questions/10908877/extracting-a-zipfile-to-memory)
self.in_memory_zip = StringIO.StringIO()
# Zip creation (https://pymotw.com/2/zipfile/)
# Get a handle to the in-memory zip in append mode
#zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
# Nom du fichier zip a envoyer
zipFileName = str(uuid.uuid4()) + ".zip";
#b64_fileContent = base64.b64encode(self.in_memory_zip.read())
# TODO : temp : on genere fichier physique parce que in_memory_zip genere un zip vide pour l'instant
localFileName = tempfile.gettempdir() + '/' + zipFileName
zf = zipfile.ZipFile(localFileName,
mode='w',
compression=zipfile.ZIP_DEFLATED,
)
try:
# get creation fields from payload
try:
formdata = FormData(json.loads(request.body), CREATION_SCHEMA)
except ValueError as e:
raise ParameterTypeError(e.message)
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "commune_raw=", formdata.values['commune_raw']
#return
if formdata.attachments:
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "nb attach: ", len(formdata.attachments)
for key, attachment in formdata.attachments.items():
filename = attachment.get('filename') or 'file%s.bin' % num
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "key: ", key, " ; filename: ", filename
content = base64.b64decode(attachment.get('content') or '')
#b64_fileContent = attachment.get('content')
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "b64_fileContent: ", b64_fileContent
try:
#zf.writestr("Pieces/"+filename, content)
# pour l'instant test en dur avec nom du cerfa pour le CU
if "cerfa" in key:
if (not formdata.values['cerfa_nom']) or formdata.values['cerfa_nom'] == '':
return {'err': 1, 'message': 'Unknown cerfa_nom'}
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "cerfa_nom: ", formdata.values['cerfa_nom']
filenameInZip = formdata.values['cerfa_nom'] + ".pdf"
else:
if len(key.split("_")) == 4:
obj, idPiece, codePiece, noPiece = key.split("_")
filenameInZip = "Pieces/"+ idPiece + "-" + codePiece + "-" + noPiece
else:
obj, idPiece, codePiece = key.split("_")
filenameInZip = "Pieces/"+ idPiece + "-" + codePiece
if "." in filename:
filenameInZip += filename[filename.rfind("."):]
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "filenameInZip: ", filenameInZip
zf.writestr(filenameInZip, content)
except ValueError as e:
raise ParameterTypeError(e.message)
zf.close()
'''
os.remove(localFileName)
return
'''
with open(localFileName, "rb") as image_file:
b64_fileContent = base64.b64encode(image_file.read())
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test apres:", b64_fileContent
# test base64
#b64_fileContent = "UEsDBBQAAAAAAMqEQUzI2HQpGgAAABoAAAAKAAAAdGVzdDAxLnR4dHRlc3QgYmFzZTY0IG1pbmkgdG90byB0YXRhUEsBAhQAFAAAAAAAyoRBTMjYdCkaAAAAGgAAAAoAAAAAAAAAAQAgAAAAAAAAAHRlc3QwMS50eHRQSwUGAAAAAAEAAQA4AAAAQgAAAAAA"
# size_max doit etre un multiple de 4 pour avoir un nb de caracteres valide en base 64 (car 3 octets y sont encodes sur 4 caracteres)
size_max = 16777216 # 16 mo, choisi arbitrairement pour ne pas envoyer trop d'un coup en http post
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test avant le sendfile"
for x in range(0, len(b64_fileContent)/size_max + 1):
#respHttp = self.requests.post('https://api-rec.grandlyon.com/ads-sendfile-dev/sendfile.aspx',
respHttp = self.requests.post(self.sendfile_ws_url,
data={'fileName': self.dirname+zipFileName,
'b64_fileContent': b64_fileContent[x*size_max:(x+1)*size_max],
'part': str(x),
'total': int(len(b64_fileContent)/size_max)}
) #.json()
finally:
os.remove(localFileName)
message = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://tempuri.org/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays" '
message += 'xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><ns1:Body><ns0:NotifierDepotDossier>'
message += '<ns0:token>'+self.get_token_cartads()+'</ns0:token>'
message += '<ns0:nCommune>'+formdata.values['commune_raw'].encode('ascii', errors='xmlcharrefreplace')+'</ns0:nCommune>'
message += '<ns0:coTypeDossier>'+formdata.values['type_dossier'].encode('ascii', errors='xmlcharrefreplace')+'</ns0:coTypeDossier>'
message += '<ns0:nomArchive>'+zipFileName+'</ns0:nomArchive>'
message += '<ns0:emailDemandeur>'+formdata.values['email'].encode('ascii', errors='xmlcharrefreplace')+'</ns0:emailDemandeur>'
message += '<ns0:typeCompteUtilisateur>'+self.get_type_compte_utilisateur()+'</ns0:typeCompteUtilisateur>'
message += '<ns0:informationsComplementaires>'
message += '<arr:KeyValueOfstringstring><arr:Key>traitementImmediat</arr:Key><arr:Value>1</arr:Value></arr:KeyValueOfstringstring>'
message += '<arr:KeyValueOfstringstring><arr:Key>idDossierExterne</arr:Key><arr:Value>'+formdata.values['tracking_code']+'</arr:Value></arr:KeyValueOfstringstring>'
message += '</ns0:informationsComplementaires>'
message += '</ns0:NotifierDepotDossier></ns1:Body></SOAP-ENV:Envelope>'
headers = {'Authorization': self.get_token(),
'SOAPAction':'"http://tempuri.org/IServicePortail/NotifierDepotDossier"',
'Content-Type': 'text/xml; charset=utf-8'}
#headers = u'Content-Length: 844 | Accept-Encoding: gzip, deflate | SOAPAction: "http://tempuri.org/IServicePortail/NotifierDepotDossier" | Accept: */* | User-Agent: python-requests/2.4.3 CPython/2.7.9 Linux/3.16.0-4-amd64 | Connection: keep-alive | Content-Type: text/xml; charset=utf-8 | '
#headers += u'Authorization: Bearer 458931e2-fbac-3087-875c-e0833d66f620' # + self.get_token()
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test avant le NotifierDepotDossier"
#TODO: faire en soap comme les autres ou adapter url pour prod
resp = self.requests.post('https://api-rec.grandlyon.com/ads-rec-portail/',
data=message,
headers=headers)
#TODO : a voir comment on passe info complementaires avec suds (traitementImmediat a 1, id dossier externe, ...)
# fonctionne mais on sait pas comment passer info complementaires
'''
client = self.get_client('cartads-portail.wsdl')
resp = client.service.NotifierDepotDossier(self.get_token_cartads(),
formdata.values['commune_raw'],
formdata.values['type_dossier'],
zipFileName,
formdata.values['email'],
self.get_type_compte_utilisateur(),
''
)
'''
'''
# en utilisant factory.create de suds, mais fonctionne pas du tout :
#rajoute un ns0:token autour de tous les param... manque un element regroupant le type complexe dans le wsdl ? : <ns0:NotifierDepotDossier><ns0:token>...</ns0:token></ns0:NotifierDepotDossier>
notifierDepotDossier = client.factory.create('NotifierDepotDossier')
notifierDepotDossier.token = self.get_token_cartads()
notifierDepotDossier.nCommune = formdata.values['commune_raw']
notifierDepotDossier.coTypeDossier = formdata.values['type_dossier']
notifierDepotDossier.nomArchive = zipFileName
notifierDepotDossier.emailDemandeur = formdata.values['email']
notifierDepotDossier.typeCompteUtilisateur = self.get_type_compte_utilisateur()
#notifierDepotDossier.informationsComplementaires
resp = client.service.NotifierDepotDossier(notifierDepotDossier)
'''
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test avant le return"
#return {'data': sudsobject_to_dict(resp), 'respHttp': respHttp.content, 'length': len(b64_fileContent)}
return {'respHttp': respHttp.content, 'length': len(b64_fileContent), 'err': 0}
@classmethod
def creation_fields(cls):
'''used in cartads_detail.html template'''
return list_schema_fields(CREATION_SCHEMA)
def get_token_cartads(self):
#TODO : a encoder d'apres les exemples php et c# fournis par GFI
#07/05/2018, avec "cle-secrete-gfi!", "!gf1-cl3-s3cr3t3", utilisée dans CartADS de REC :
#{'date':'23/01/2028 15:10:00','login':'gnm','password':'Gu!che7'}
if self.cle_token_gfi == "cle-secrete-gfi!":
return "ieTluf0q6vwjitxope55YZ2ud0CEtuO9BBHr2hQaxySeDrz66mntHl83Wqj7oadMSyZqwSkzVdZJrQ92Zg2p3bwkAuv5yUzwmpBfdtAYYLE="
#07/05/2018, avec "cle-secrete-gly!", "!gl1-cl3-s3cr3t3", utilisée dans CartADS de DEV :
#{'date':'23/01/2028 15:10:00','login':'gnm','password':'Gu!che7'}
if self.cle_token_gfi == "cle-secrete-gly!":
return "HQgzlNovC9eyesEH5Fl6P8aBDYkgtVDq/GiOxLL3XfhcsiRecO3IJyqXro6Z3wekk08QwXvVx9tqeqzk81MS8b4LYBhUkj2bFeiDGBsLHFc="
def get_type_compte_utilisateur(self):
#TODO : a encoder d'apres les exemples php et c# fournis par GFI
return 'ContactService'
@endpoint(perm='can_access')
def get_communes(self, request):
resp = self.get_client('cartads-portail.wsdl').service.GetCommunes(self.get_token_cartads(),
self.get_type_compte_utilisateur()
)
'''
#TODO: Ca serait mieux mais ca marche pas...
resp = self.get_client('cartads-portail.wsdl').service.GetCommunes({
'token': self.get_token_cartads(),
'typeCompteUtilisateur': self.get_type_compte_utilisateur(),
})'''
return {'data': sudsobject_to_dict(resp)}
@endpoint(perm='can_access')
def get_objets_demande(self, request, type_dossier):
if len(type_dossier) != 2:
raise ParameterTypeError("invalid type_dossier parameter")
resp = self.get_client('cartads-portail.wsdl').service.GetObjetsDemande(self.get_token_cartads(), type_dossier)
#TODO: gerer un cache au cas ou cartads repond pas
if resp == None and type_dossier=="PC":
data = [{'text': "Permis de construire pour une maison individuelle et / ou ses annexes", 'id': 24}, {'text': "Autre permis de construire", 'id': 25}]
return {'data': data}
dict_resp = sudsobject_to_dict(resp)
# On parcourt la liste pour la mettre sous la forme id, text, pour l'utiliser comme source de donnees dans le formulaire
out = []
for objet in dict_resp['KeyValueOfintstring']:
out_item = {}
out_item['id'] = objet["Key"]
out_item['text'] = objet["Value"]
out.append(out_item)
def getKey(objet):
return objet['id']
return {'data': sorted(out, key=getKey)}
@endpoint(perm='can_access')
def get_liste_pdf(self, request, type_dossier):
resp = self.get_client('cartads-portail.wsdl').service.GetListePdf(self.get_token_cartads(),
type_dossier,
self.get_type_compte_utilisateur()
)
return {'data': sudsobject_to_dict(resp)}
@endpoint(perm='can_access')
def get_pieces(self, request, type_dossier, objet_demande):
resp = self.get_client('cartads-portail.wsdl').service.GetPieces(self.get_token_cartads(),
type_dossier,
objet_demande
)
return {'data': sudsobject_to_dict(resp)}
@endpoint(perm='can_access')
def get_id_dossier(self, request, tracking_code, date_dossier):
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "date_dossier: ", date_dossier
# TODO: faire plus simple si gfi explique comment obtenir l'IdDossier a partir de l'IdDossierExterne en pull (et pas qu'en push dans leur notif qui marche pas)
# Renvoie les dossiers a la date demandee
#TODO: faire param pour client1
resp = self.get_client('cartads-recherchedossier.wsdl').service.GetDossiersSelonDerniereEtape(
'client1',
date_dossier,
date_dossier
)
dict_resp = sudsobject_to_dict(resp)
def getOrder(objet):
return objet['IdDossier']* -1
# On parcourt la liste a partir de la fin pour chercher le bon dossier
idDossierOut = ''
nomDossierOut = ''
for objet in sorted(dict_resp['DossierEtape'], key=getOrder):
resp_dossier = self.get_client('cartads-dossier.wsdl').service.GetInfosDossier(self.get_token_cartads(), objet["IdDossier"])
dict_resp_dossier = sudsobject_to_dict(resp_dossier)
if dict_resp_dossier["IdDossierExterne"] == tracking_code:
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "IdDossier: ", dict_resp_dossier["IdDossier"]
idDossierOut = dict_resp_dossier["IdDossier"]
nomDossierOut = dict_resp_dossier["NomDossier"]
break;
print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "idDossierOut: ", idDossierOut
return {'data': {'IdDossier': idDossierOut, 'NomDossier': nomDossierOut} }
@endpoint(perm='can_access')
def get_etape(self, request, id_dossier):
resp = self.get_client('cartads-etapedossier.wsdl').service.GetEtapesDossier(self.get_token_cartads(), id_dossier, '')
# sort by IdEtapeDossier descending to get the last stage
def getKey(objet):
return -1 * objet['IdEtapeDossier']
return {'data': sorted(sudsobject_to_dict(resp)['EtapeDossier'], key=getKey)}
@endpoint(perm='can_access')
def get_infos_dossier(self, request, id_dossier):
resp = self.get_client('cartads-dossier.wsdl').service.GetInfosDossier(self.get_token_cartads(), id_dossier)
return {'data': sudsobject_to_dict(resp)}
def write_wcs_page(self, request, no_page, label_page, output_string, objet, id):
output_string += u"<field>\n"
output_string += u" <label>"+label_page+u"</label>\n"
output_string += u" <type>page</type>\n"
output_string += u" <condition>\n"
output_string += u" <type>python</type>\n"
output_string += u' <value>form_var_objet_raw == "'+str(objet["id"]).decode('utf8')+u'"'
if no_page==u"5":
output_string += u' and form_var_demolition == "Oui"'
output_string += u' </value>\n'
output_string += u" </condition><id>"+str(id).decode('utf8')+u"</id>\n"
output_string += u" </field><field>\n"
output_string += u' <label>&lt;p&gt;&lt;strong&gt;&lt;span style="color: rgb(134, 134, 134); font-family: Roboto, sans-serif; letter-spacing: 1px;"&gt;'+no_page+'. &lt;/span&gt;&lt;strong class="label" id="label'+str(id).decode('utf8')+u'"&gt;'+label_page+'&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;</label>\n'
output_string += u" <type>comment</type>\n"
# on incremente l'id du label apres rempli l'id labelxxxx du commentaire du label
id += 1
output_string += u" <id>"+str(id).decode('utf8')+u"</id>\n"
id += 1
output_string += u" </field><field>\n"
output_string += u' <label>[is form_option_type_dossier "foo"] [end]'
output_string += u"\n"
output_string += u'&lt;span id="logo_commune"&gt;&lt;/span&gt;\n'
output_string += u"\n"
output_string += u"\n"
output_string += u'&lt;script type="text/javascript"&gt;\n'
output_string += u"function slugify(text)\n"
output_string += u"{\n"
output_string += u" return text.toString().toLowerCase()\n"
output_string += u" .replace(/\s+/g, '-') // Replace spaces with -\n"
output_string += u" .replace(/\'/g, '-') // Replace ' with -\n"
output_string += u" .replace(/&#244;/g, 'o').replace(/&#233;/g, 'e').replace(/&#232;/g, 'e') // Remove accent\n"
output_string += u" .replace(/[^\w\-]+/g, '') // Remove all non-word chars\n"
output_string += u" .replace(/\-\-+/g, '-') // Replace multiple - with single -\n"
output_string += u" .replace(/^-+/, '') // Trim - from start of text\n"
output_string += u" .replace(/-+$/, ''); // Trim - from end of text\n"
output_string += u"}\n"
output_string += u"function setLogo()\n"
output_string += u"{\n"
output_string += u' var selectedText ="[form_var_commune]";\n'
output_string += u" var communeChanged = slugify(selectedText);\n"
output_string += u" // Pour enlever arrondissement de Lyon\n"
output_string += u' if( selectedText.startsWith("Lyon") ) communeChanged = "lyon"\n'
output_string += u' $("#logo_commune").html(\'&lt;img src="[portal_url]static/grandlyon-gnm/producers/\'+communeChanged+\'.png" /&gt;\');\n'
output_string += u"}\n"
output_string += u"setLogo();\n"
output_string += u"&lt;/script&gt;\n"
output_string += u"\n"
output_string += u"</label>\n"
output_string += u" <type>comment</type>\n"
output_string += u" <extra_css_class>imgCommune</extra_css_class>\n"
output_string += u" <id>"+str(id).decode('utf8')+u"</id>\n"
id += 1
if no_page==u"3":
output_string += u" </field><field>\n"
output_string += u" <label>&lt;p&gt;&lt;strong&gt;Votre dossier est pr&amp;ecirc;t &amp;agrave; &amp;ecirc;tre d&amp;eacute;pos&amp;eacute;.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Merci de nous faire parvenir les pi&amp;egrave;ces ci-dessous.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</label>\n"
output_string += u" <type>comment</type>\n"
output_string += u" <id>"+str(id).decode('utf8')+u"</id>\n"
id += 1
output_string += u" </field><field>\n"
output_string += u" <label>Cerfa rempli</label>\n"
output_string += u" <type>file</type>\n"
output_string += u" <required>True</required>\n"
output_string += u" <varname>objet"+str(objet["id"]).decode('utf8')+u"_cerfa</varname>\n"
output_string += u" <in_listing>False</in_listing>\n"
output_string += u" <prefill>\n"
output_string += u" <type>none</type>\n"
output_string += u" </prefill><max_file_size>50M</max_file_size>\n"
output_string += u" <allow_portfolio_picking>True</allow_portfolio_picking>\n"
output_string += u" <id>"+str(id).decode('utf8')+u"</id>\n"
id += 1
output_string += u" </field>\n"
return output_string, id
@endpoint(perm='can_access')
def write_wcs_files(self, request, type_dossier):
h = HTMLParser.HTMLParser() # h.unescape(string) decode le html qui vient du web service en unicode : http://fredericiana.com/2010/10/08/decoding-html-entities-to-text-in-python/
output_string = u"<!--#### A inserer a partir du field 'Pi&#232;ces obligatoires' jusqu'a la fin des </fields> -->\n"
# page en cours de construction : 0 = pieces obligatoires
current_page = 0
dict_resp = self.get_objets_demande(request, type_dossier)
for objet in dict_resp['data']:
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "objet: ", objet
#return {'data': dict_resp}
resp = self.get_pieces(request, type_dossier, objet["id"])
dict_resp = resp["data"]
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "dict_resp: ", dict_resp
date_file = datetime.datetime.now()
#id de field par objet pour essayer d'avoir un id invariant pour quand on reimporte le formulaire
id_par_objet = 100*objet["id"]
# page en cours de construction : 0 = pieces obligatoires
current_page = 0
output_string, id_par_objet = self.write_wcs_page(request, u"3", u"Pi&#232;ces obligatoires", output_string, objet, id_par_objet)
for piece in dict_resp['Piece']:
#print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "IdPiece: ", piece["IdPiece"]
#for key, value in piece.items():
#print >> open('/home/grandlyon/log/'+type_dossier+'_'+date_file.strftime('%Y%m%d%H%M%S')+'.wcs', 'a+'), key,": ", value
#self.print_wcs_files(type_dossier, date_file, key+": "+str(value))
if piece["Reglementaire"] == False and current_page == 0:
# page en cours de construction : 1 = pieces selon le dossier
current_page = 1
output_string, id_par_objet = self.write_wcs_page(request, u"4", u"Pi&#232;ces selon le dossier", output_string, objet, id_par_objet)
if str(piece["CodePiece"]).startswith("PCA") and current_page == 1:
# page en cours de construction : 2 = pieces pour demolition
current_page = 2
output_string, id_par_objet = self.write_wcs_page(request, u"5", u"Pi&#232;ces pour d&#233;molition", output_string, objet, id_par_objet)
#id de field par objet et piece pour essayer d'avoir un id invariant pour quand on reimporte le formulaire
# Attention l'id ne doit pas contenir de - sinon provoque Internal Server error a l'import dans wcs
id_par_piece = str(objet["id"]) + '_' + str(piece["IdPiece"])
output_string += u"<field>\n"
output_string += u" <label>"+str(piece["CodePiece"]).decode('utf8')+u" - "+h.unescape(piece["Libelle"])+u"</label>\n"
output_string += u" <type>file</type>\n"
output_string += u" <extra_css_class>plus0</extra_css_class>\n"
output_string += u" <required>"+str(piece["Reglementaire"]).title().decode('utf8')+u"</required>\n"
hint = u""
if piece["Descriptif"]: hint = h.unescape(piece["Descriptif"])
output_string += u" <hint>"+hint+u"</hint>\n"
output_string += u" <varname>objet"+str(objet["id"]).decode('utf8')+u"_"+str(piece["IdPiece"]).decode('utf8')+u"_"+str(piece["CodePiece"]).decode('utf8')+u"</varname>\n"
output_string += u" <in_listing>False</in_listing>\n"
output_string += u" <prefill>\n"
output_string += u" <type>none</type>\n"
output_string += u" </prefill><max_file_size>50M</max_file_size>\n"
output_string += u" <allow_portfolio_picking>True</allow_portfolio_picking>\n"
output_string += u" <id>"+str(id_par_piece).decode('utf8')+u"</id>\n"
output_string += u"</field>\n"
# ajoute 5 PJ supplementaires par pièce
for i in range(5):
output_string += u" <field>\n"
output_string += u" <label>"+str(piece["CodePiece"]).decode('utf8')+u" - "+h.unescape(piece["Libelle"])+u" "+str(i+1)+u"</label>\n"
output_string += u" <type>file</type>\n"
output_string += u" <extra_css_class>plus plus"+str(i+1)+u"</extra_css_class>\n"
output_string += u" <required>False</required>\n"
output_string += u" <varname>objet"+str(objet["id"]).decode('utf8')+u"_"+str(piece["IdPiece"]).decode('utf8')+u"_"+str(piece["CodePiece"]).decode('utf8')+u"-"+str(i+1)+u"</varname>\n"
output_string += u" <in_listing>False</in_listing>\n"
output_string += u" <prefill>\n"
output_string += u" <type>none</type>\n"
output_string += u" </prefill><max_file_size>50M</max_file_size>\n"
output_string += u" <allow_portfolio_picking>True</allow_portfolio_picking>\n"
output_string += u" <id>"+str(id_par_piece).decode('utf8')+u"_"+str(i+1)+u"</id>\n"
output_string += u" </field>\n"
output_string += u" </fields>\n"
output_string = output_string.encode('ascii', errors='xmlcharrefreplace')
print >> open('/home/grandlyon/log/'+type_dossier+'_'+date_file.strftime('%Y%m%d%H%M%S')+'.wcs', 'a+'), output_string
return {'data': output_string}