diff --git a/cartads/models.py b/cartads/models.py index 79317a2..88c2aab 100644 --- a/cartads/models.py +++ b/cartads/models.py @@ -188,10 +188,10 @@ class CartADS(BaseResource): if formdata.attachments: - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "nb attach: ", len(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 + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "key: ", key, " ; filename: ", filename content = base64.b64decode(attachment.get('content') or '') @@ -203,8 +203,10 @@ class CartADS(BaseResource): 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'] + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "cerfa_nom: ", formdata.values['cerfa_nom'] filenameInZip = formdata.values['cerfa_nom'] + ".pdf" + elif "autres_demandeurs" in key: + filenameInZip = "Fiches_complementaires/cerfa_"+ key + ".pdf" else: if len(key.split("_")) == 4: obj, idPiece, codePiece, noPiece = key.split("_") @@ -214,7 +216,7 @@ class CartADS(BaseResource): filenameInZip = "Pieces/"+ idPiece + "-" + codePiece if "." in filename: filenameInZip += filename[filename.rfind("."):] - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "filenameInZip: ", filenameInZip + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "filenameInZip: ", filenameInZip zf.writestr(filenameInZip, content) except ValueError as e: @@ -242,7 +244,7 @@ class CartADS(BaseResource): # 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" + ###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', @@ -280,7 +282,7 @@ class CartADS(BaseResource): #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" + ###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/', @@ -315,7 +317,7 @@ class CartADS(BaseResource): resp = client.service.NotifierDepotDossier(notifierDepotDossier) ''' - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test avant le return" + ###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} @@ -400,7 +402,7 @@ class CartADS(BaseResource): @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 + ###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 @@ -426,7 +428,7 @@ class CartADS(BaseResource): nomDossierOut = dict_resp_dossier["NomDossier"] break; - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "idDossierOut: ", idDossierOut + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "idDossierOut: ", idDossierOut return {'data': {'IdDossier': idDossierOut, 'NomDossier': nomDossierOut} } @endpoint(perm='can_access') @@ -446,7 +448,6 @@ class CartADS(BaseResource): def get_pieces_dossier_a_completer(self, request, id_dossier): resp = self.get_client('cartads-piece.wsdl').service.GetPiecesDossierACompleter(self.get_token_cartads(), id_dossier) dict_resp = sudsobject_to_dict(resp) - #return {'data': sudsobject_to_dict(resp)} if not 'PieceDossier' in dict_resp: return {'data': None, 'err': 0} @@ -460,6 +461,30 @@ class CartADS(BaseResource): out_item['Descriptif'] = objet["Descriptif"] out_item['IdDosPiece'] = objet["IdDosPiece"] out_item['CodePiece'] = objet["CodePiece"] + out_item['IdPiece'] = objet["IdPiece"] + out.append(out_item) + + def getKey(objet): + return objet['CodePiece'] + return {'data': sorted(out, key=getKey)} + + @endpoint(perm='can_access') + def get_pieces_daact(self, request, id_dossier): + resp = self.get_client('cartads-piece.wsdl').service.GetPiecesDaact(self.get_token_cartads(), id_dossier) + dict_resp = sudsobject_to_dict(resp) + + if not 'PieceDossier' in dict_resp: + return {'data': None, 'err': 0} + + # 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['PieceDossier']: + out_item = {} + out_item['id'] = objet["IdPiece"] + out_item['text'] = objet["CodePiece"] + " - " + objet["LibellePiece"] + out_item['Descriptif'] = objet["Descriptif"] + out_item['CodePiece'] = objet["CodePiece"] + out_item['IdPiece'] = objet["IdPiece"] out.append(out_item) def getKey(objet): @@ -474,47 +499,81 @@ class CartADS(BaseResource): except ValueError as e: raise ParameterTypeError(e.message) - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "piece_compl_var_fichier: ", formdata.values['piece_compl_var_fichier'] - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "piece_compl_var_fichier_raw: ", formdata.values['piece_compl_var_fichier_raw'] + if not formdata.values['id_dossier']: + return {'data': 'no id_dossier', 'err': 1} + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "id_dossier: ", formdata.values['id_dossier'] + + # si c'est une piece complementaire (pas doc ni daact) + if formdata.values['docDaact'] == '': + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "piece_compl_var_fichier: ", formdata.values['piece_compl_var_fichier'] + fichier_raw = formdata.values['piece_compl_var_fichier_raw'] + filename_in = formdata.values['piece_compl_var_fichier'] + filename_out = formdata.values['piece_compl_var_infos_IdPiece'] + "-" + formdata.values['piece_compl_var_infos_CodePiece'] + "-" + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + if "." in filename_in: + filename_out += filename_in[filename_in.rfind("."):] + elif formdata.values['docDaact'] == 'doc': + fichier_raw = formdata.values['piece_doc_var_fichier_raw'] + filename_out = "cerfa.pdf" + elif formdata.values['docDaact'] == 'daact': + fichier_raw = formdata.values['piece_daact_var_fichier_raw'] + filename_out = "cerfa.pdf" + elif formdata.values['docDaact'] == 'pieceDaact': + fichier_raw = formdata.values['piece_pieceDaact_var_fichier_raw'] + filename_in = formdata.values['piece_pieceDaact_var_fichier'] + filename_out = formdata.values['piece_pieceDaact_var_infos_IdPiece'] + "-" + formdata.values['piece_pieceDaact_var_infos_CodePiece'] + "-" + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + if "." in filename_in: + filename_out += filename_in[filename_in.rfind("."):] + else: + return {'data': 'unknown docDaact: ' + formdata.values['docDaact'], 'err': 1} - #TODO: faire un get de https://demarches.guichet-dev.grandlyon.com/permis-de-construire/21/files/form-piece_compl_depose-fichier/plan-situation.txt + fichier_content_base64 = fichier_raw['content'] + message = u'' + message += u'' + message += u''+str(self.get_token_cartads()).decode('utf8')+'' + message += u''+filename_out+'' + #TODO: voir s'il faut passer la longueur du fichier source ou encode en base64 + message += u''+str(len(fichier_content_base64))+'' + message += u'' + if formdata.values['docDaact'] == '': + #piece complementaire + message += u'idDosPiece'+str(formdata.values['piece_compl_var_infos_IdDosPiece']).decode('utf8')+u'' + else: + #piece ouverture chantier (doc) ou achevement (daact) ou piece achevement (pieceDaact) + message += u'docDaact'+str(formdata.values['docDaact']).decode('utf8')+u'' + if formdata.values['docDaact'] == 'pieceDaact': + #piece daact + message += u'idPieceDaact'+str(formdata.values['piece_pieceDaact_var_infos_IdPiece']).decode('utf8')+u'' + message += u'renameFiletrue' + message += u'' + message += u''+str(formdata.values['id_dossier']).decode('utf8')+u'' + message += u'' + message += u'' + message += u''+str(fichier_content_base64).decode('utf8')+u'' + #message += 'dGVzdA==' + message += u'' - if not formdata.values['piece_compl_var_fichier']: - return {'data': 'no piece_compl_var_fichier', 'err': 1} - - message = '' - message += '' - message += ''+self.get_token_cartads()+'' - message += ''+formdata.values['piece_compl_var_fichier']+'' - message += ''+length(formdata.values['piece_compl_var_fichier_raw'])+'' - message += '' - message += 'docDaactdoc' - message += '' - message += ''+'436205'+'' - message += '' - message += '' - message += ''+formdata.values['piece_compl_var_fichier_raw']+'' - message += '' - - headers = {'Authorization': self.get_token(), - 'SOAPAction':'"http://tempuri.org/IServiceDocumentation/UploadFile"', - 'Content-Type': 'text/xml; charset=UTF-8'} + #headers and message must be str and not unicode to avoid SSL3_WRITE_PENDING : bad write retry error (cf. https://github.com/urllib3/urllib3/issues/855) + headers = {'Authorization': self.get_token().encode('utf-8'), + 'SOAPAction':'"http://tempuri.org/IServiceDocumentation/UploadFile"'.encode('utf-8'), + 'Content-Type': 'text/xml; charset=UTF-8'.encode('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 UploadFile" - - print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "message: " + message + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "test avant le UploadFile" + #print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "message: " + message #TODO: faire en soap comme les autres ou adapter url pour prod resp = self.requests.post('https://api-rec.grandlyon.com/ads-rec-documentation/', - data=message, + data=message.encode('utf-8'), headers=headers) + + ###print >> open('/home/grandlyon/log/cartads.debug', 'a+'), datetime.datetime.now(), "resp.content: " + resp.content + return {'data': resp.content, 'err': 0} @@ -596,7 +655,7 @@ class CartADS(BaseResource): @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"\n" + output_string = u"\n" # page en cours de construction : 0 = pieces obligatoires current_page = 0 @@ -677,6 +736,6 @@ class CartADS(BaseResource): output_string += u" \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 + ###print >> open('/home/grandlyon/log/'+type_dossier+'_'+date_file.strftime('%Y%m%d%H%M%S')+'.wcs', 'a+'), output_string return {'data': output_string} diff --git a/extra/static/droitdusol.css b/extra/static/droitdusol.css index 606523c..f49e762 100644 --- a/extra/static/droitdusol.css +++ b/extra/static/droitdusol.css @@ -1,7 +1,6 @@ /* img commune */ @media screen and (min-width: 1000px) { - .formdef-permis-de-construire .imgCommune img, - .formdef-certificat-d-urbanisme .imgCommune img { + .formdef-category-logement .imgCommune img { position: absolute; top: 132px; left: 500px; @@ -10,59 +9,59 @@ } /* File upload styling for permis de construire */ -.formdef-permis-de-construire .FileWithPreviewWidget { +.formdef-category-logement .FileWithPreviewWidget { display: flow-root; border-bottom: 0.1em solid #80808052; background-color: #d3d3d333; } -.formdef-permis-de-construire .FileWithPreviewWidget .title, -.formdef-permis-de-construire .FileWithPreviewWidget .content, -.formdef-permis-de-construire .FileWidget { +.formdef-category-logement .FileWithPreviewWidget .title, +.formdef-category-logement .FileWithPreviewWidget .content, +.formdef-category-logement .FileWidget { display: inline-block; } -.formdef-permis-de-construire .widget .title { +.formdef-category-logement .widget .title { padding: 10px; } -.formdef-permis-de-construire form.quixote div.widget { +.formdef-category-logement form.quixote div.widget { margin-bottom: 5px; } -.formdef-permis-de-construire .FileWithPreviewWidget .content { +.formdef-category-logement .FileWithPreviewWidget .content { position: relative; float: right; max-width: 258px; height: 35px; } -.formdef-permis-de-construire .FileWithPreviewWidget.widget-required.has-no-file { +.formdef-category-logement .FileWithPreviewWidget.widget-required.has-no-file { background-color: #ff000030; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file { +.formdef-category-logement .FileWithPreviewWidget.has-file { background-color: #b9d4b9; } -.formdef-permis-de-construire .FileWithPreviewWidget .fileprogress, -.formdef-permis-de-construire .FileWithPreviewWidget .fileinfo { +.formdef-category-logement .FileWithPreviewWidget .fileprogress, +.formdef-category-logement .FileWithPreviewWidget .fileinfo { position: relative; top: -35px; } -.formdef-permis-de-construire .FileWithPreviewWidget.widget-readonly .fileinfo { +.formdef-category-logement .FileWithPreviewWidget.widget-readonly .fileinfo { top: 10px; padding-right: 10px; } -.formdef-permis-de-construire .FileWithPreviewWidget .hint { +.formdef-category-logement .FileWithPreviewWidget .hint { position: relative; color:#ffffff00; padding: 3px 8px 5px 8px; top: -10px; left: -270px; } -/*.formdef-permis-de-construire .FileWithPreviewWidget .hint:hover,*/ -.formdef-permis-de-construire .FileWithPreviewWidget .hint:active { +/*.formdef-category-logement .FileWithPreviewWidget .hint:hover,*/ +.formdef-category-logement .FileWithPreviewWidget .hint:active { position: relative; background-color: #d0e3ff; border: 0.01em solid #4e4e4e; color: #000; z-index: 99999; } -.formdef-permis-de-construire .FileWithPreviewWidget .hint:before { +.formdef-category-logement .FileWithPreviewWidget .hint:before { position: relative; content: "ⓘ"; font-size: 1.3em; @@ -71,35 +70,35 @@ top: -20px; cursor: help; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus label, -.formdef-permis-de-construire .FileWithPreviewWidget.has-file .error, -.formdef-permis-de-construire .FileWithPreviewWidget.has-file .hint, -.formdef-permis-de-construire .FileWithPreviewWidget.plus { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus label, +.formdef-category-logement .FileWithPreviewWidget.has-file .error, +.formdef-category-logement .FileWithPreviewWidget.has-file .hint, +.formdef-category-logement .FileWithPreviewWidget.plus { display: none; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus { display: flow-root; position: relative; top: -7px; background-color: #b9d4b9; height: 43px; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus2 { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus2 { top: -14px; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus3 { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus3 { top: -21px; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus4 { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus4 { top: -28px; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus5 { +.formdef-category-logement .FileWithPreviewWidget.has-file + .FileWithPreviewWidget.plus5 { top: -35px; } -.formdef-permis-de-construire .FileWithPreviewWidget.plus.widget-readonly.has-no-file { +.formdef-category-logement .FileWithPreviewWidget.plus.widget-readonly.has-no-file { display: none; } -.formdef-permis-de-construire .FileWithPreviewWidget.has-no-file .error { +.formdef-category-logement .FileWithPreviewWidget.has-no-file .error { left: -180px; position: relative; line-height: 0px; @@ -109,10 +108,10 @@ } /* case à cocher */ -.formdef-permis-de-construire .checkbox-cerfa .content, -.formdef-permis-de-construire .checkbox-cerfa .title { +.formdef-category-logement .checkbox-cerfa .content, +.formdef-category-logement .checkbox-cerfa .title { display: inline; } -.formdef-permis-de-construire .checkbox-cerfa .content { +.formdef-category-logement .checkbox-cerfa .content { float: left; }