managefile.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. from django.shortcuts import render
  2. from django.http import HttpResponse,HttpResponseRedirect,FileResponse
  3. from django.urls import reverse
  4. from django.db import IntegrityError
  5. from .models import *
  6. from config.views import *
  7. from att.views import *
  8. from django.conf import settings
  9. from django.conf.urls.static import static
  10. from django.contrib.auth import authenticate
  11. import mimetypes
  12. from random import randint
  13. import csv
  14. import time
  15. import datetime
  16. import zipfile
  17. #pip install python-codicefiscale
  18. from codicefiscale import codicefiscale
  19. import os
  20. # come sono gestiti i file nella configurazione:
  21. # MEDIA_ROOT=os.path.join(settings.BASE_DIR,'static/upload')
  22. # che diventa = os.path.join(settings.BASE_DIR,getConfig('DocPath'))
  23. # inoltre devo aver fatto qualche casino oggi 9.8.24 con i copia e incolla. ho dovuto rivedere tutto il file
  24. # il terrore si impossessa di me. sta storia del cvs non e' esattamente chiara
  25. # questo blocco rimuove fisicamente il file prima della sua rimozione logica nel db
  26. def delete_file(documento):
  27. file_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),documento.utente.azienda.partitaiva,documento.utente.codicefiscale,documento.storage)
  28. print('Path completa:',file_path)
  29. if os.path.isfile(file_path):
  30. print('rimozione fisica file:',file_path)
  31. try:
  32. os.remove(file_path)
  33. except OSError as ose:
  34. print('errore nella rimozione del file:',ose)
  35. # impacchetta il file e procede a fornire il file via web
  36. def download_file(request,uid):
  37. utente = Utenti.objects.get(pk=uid)
  38. file_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),documento.utente.azienda.partitaiva,documento.utente.codicefiscale,utente.storage)
  39. print('Path completa da Basedir:',file_path)
  40. if utente.storage and os.path.isfile(file_path):
  41. try:
  42. fl = open(file_path, 'rb')
  43. except Exception as er:
  44. print('errore',er)
  45. data=dict()
  46. data['errore']="File non esistente o non ancora disponibile"
  47. data['utente'] = utente
  48. return render(request,'documento.error.html',data)
  49. else:
  50. print('il file non esiste',file_path)
  51. data=dict()
  52. data['errore']='File non esistente o non ancora disponibile'
  53. data['utente'] = utente
  54. return render(request,'documento.error.html',data)
  55. mime_type, _ = mimetypes.guess_type(file_path)
  56. print('file',file_path,mime_type)
  57. response = FileResponse(open(file_path,'rb'),content_type='application/pdf',as_attachment=False)
  58. #response['Content-Disposition'] = "attachment; filename=%s" % u.documento
  59. return response
  60. # upload file
  61. # procedura singolo file per singolo utente
  62. def upload_file(uploaded_file,utente,originale=False):
  63. stored_file = ''.join((str(time.time()),'.saved'))
  64. fl_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'))
  65. print('nome file',uploaded_file.name,stored_file)
  66. #modifico il file per dire alla funzione superiore se il file e' stato caricato o meno
  67. nomefile=None
  68. if originale:
  69. nomefile = uploaded_file.name
  70. else:
  71. nomefile = stored_file
  72. # vediamo se caricare o meno.
  73. # in questo caso, se il documento esiste gia', non lo carica.
  74. # come facciamo a stabilire se il documento esiste gia'?
  75. # fl_path = corrisponde a media.ROOT (che mi domando se non e' il caso di spostarlo nella configurazione)
  76. # azienda.partitaiva
  77. # utente.codicefiscale (prima era "record" e mi sono deciso a cambiarlo)
  78. try:
  79. print('posizione partitaiva',os.path.join(fl_path,utente.azienda.partitaiva))
  80. os.mkdir(os.path.join(fl_path,utente.azienda.partitaiva))
  81. except FileExistsError as fee:
  82. print('posizione partitaiva',os.path.join(fl_path,utente.azienda.partitaiva),"esistente")
  83. try:
  84. print("posizione partitaiva codicefiscale",os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale))
  85. os.mkdir(os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale))
  86. except FileExistsError as fee:
  87. print("posizione partitaiva codicefiscale",os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale),"esistente")
  88. with open(os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile),'wb+') as d:
  89. for chunk in uploaded_file.chunks():
  90. d.write(chunk)
  91. if originale:
  92. # viene richiesto il file originale piuttosto cheil file codificato con il timing
  93. print("viene restituito il file originale",os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile))
  94. return os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile)
  95. print("viene restituito il file rinominato",os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile))
  96. return stored_file
  97. # caricamento file indice (gestito in modo diverso)
  98. def upload_file_indice(uploaded_file):
  99. stored_file = ''.join((str(time.time()),'.saved'))
  100. fl_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),getConfig('DocPathIndex'))
  101. print('nome file',uploaded_file.name,stored_file)
  102. # verifica l'esistenza della directory
  103. try:
  104. os.mkdir(fl_path)
  105. except FileExistsError as fee:
  106. print(fl_path,"esistente")
  107. print('file_memorizzato',os.path.join(fl_path,stored_file))
  108. with open(os.path.join(fl_path,stored_file),'wb+') as d:
  109. for chunk in uploaded_file.chunks():
  110. d.write(chunk)
  111. return stored_file
  112. # sposta directory sulla base del codicefiscale aggiornato
  113. def rename_dir(utente,old,new):
  114. fl_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'))
  115. try:
  116. print("posizione partitaiva codicefiscale",os.path.join(fl_path,utente.azienda.partitaiva,old))
  117. os.rename(os.path.join(fl_path,utente.azienda.partitaiva,old),os.path.join(fl_path,utente.azienda.partitaiva,new))
  118. except FileExistsError as fee:
  119. print("posizione partitaiva codicefiscale old",os.path.join(fl_path,utente.azienda.partitaiva,old))
  120. print("posizione partitaiva codicefiscale new",os.path.join(fl_path,utente.azienda.partitaiva,new),"esistente")
  121. return False
  122. except FileNotFoundError as fnfe:
  123. print('non trovo la directory da rinominare')
  124. return False
  125. return True
  126. # il file caricato viene associato a un utente specifico
  127. def associafile_a_utente(singolodocumento,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None,pertutti=False):
  128. risultato = upload_file(singolodocumento,utente)
  129. documento = Documento()
  130. documento.dataupload = datetime.datetime.now()
  131. documento.utente = utente
  132. listaok = None
  133. listanotok = None
  134. listanotass = None
  135. associato = False
  136. if pertutti:
  137. documento.documento = "".join((utente.codicefiscale.strip(),"_",singolodocumento.name))
  138. else:
  139. documento.documento = singolodocumento.name
  140. print('documento.documento',documento.documento)
  141. documento.storage = risultato
  142. documento.descrizione = descrizione
  143. if 'emo_' in documento.documento.lower():
  144. print("Individuato elemento emo_ in:", documento.documento)
  145. documento.privato = True
  146. try:
  147. documento.save()
  148. setLog(8,azienda=azienda,sede=sede,utente=utente,documento=documento,amministratore=amministratore)
  149. listaok = {'n':documento.documento,'c':'documento assegnato regolarmente'}
  150. associato = True
  151. except IntegrityError as ie:
  152. print("problema di integrita', il file esiste",ie)
  153. listanotok = {'n':documento.documento,'c':'documento esistente'}
  154. if not associato:
  155. print('documento da rimuovere di nuovo',associato)
  156. listanotass = {'n':documento.documento,'c':'documento esistente'}
  157. return(listaok,listanotok,listanotass)
  158. ##################################################################################
  159. # carica file multipli. Utilizzato prevalentemente dalla gestione documenti.
  160. def save_and_load_file_multiple(listadocumenti,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None,pertutti=False,ignoraAzienda=False,ignoraSede=False,_privato=False):
  161. listaok = list()
  162. listanotok = list()
  163. listanotass = list()
  164. if azienda: print('Caricamento Multiplo,azienda',azienda.nome)
  165. if sede: print('Caricamento Multiplo,sede',sede.nome)
  166. print("Ignora le aziende",ignoraAzienda)
  167. print("Ignora le sedi",ignoraSede)
  168. print("Per tutti",pertutti)
  169. print("Privato",_privato)
  170. for singolodocumento in listadocumenti:
  171. print('singolodocumento:',singolodocumento)
  172. for ut in utente:
  173. print('utente:',ut.nome)
  174. lok = None
  175. nok = None
  176. las = None
  177. # si deve individuare il codice fiscale dell'utente
  178. if not pertutti:
  179. if ut.codicefiscale.strip() in singolodocumento.name:
  180. print('associa documento CON riferimento a codice fiscale')
  181. if ignoraAzienda:
  182. print("Effettua ricerca in tutte le aziende")
  183. lok,nok,las = associafile_a_utente(singolodocumento,request,ut,ut.azienda,sede,descrizione,amministratore)
  184. elif ignoraSede:
  185. print("Effettua ricerca in tutte le Sedi dell'azienda")
  186. lok,nok,las = associafile_a_utente(singolodocumento,request,ut,ut.azienda,sede,descrizione,amministratore)
  187. else:
  188. print("Caricamento solo per l'azienda corrente")
  189. lok,nok,las = associafile_a_utente(singolodocumento,request,ut,azienda,sede,descrizione,amministratore)
  190. else:
  191. print('il codice fiscale',ut.codicefiscale.strip()," non si trova in ",singolodocumento.name)
  192. las = {'n':singolodocumento.name,'c':'non associabile - il codice fiscale non corrisponde'}
  193. else:
  194. print('associo documento SENZA riferimento a codice fiscale')
  195. lok,nok,las = associafile_a_utente(singolodocumento,request,ut,azienda,sede,descrizione,amministratore,pertutti)
  196. if lok:
  197. listaok.append(lok)
  198. if nok:
  199. listanotok.append(nok)
  200. if las:
  201. listanotass.append(las)
  202. print('lista',listaok,listanotok,listanotass)
  203. return (listaok,listanotok,listanotass)
  204. #carica un singolofile - utilizzato prevalentemente nella pagina utente
  205. def save_and_load_file_single(listadocumenti,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None,_privato=False):
  206. """
  207. listadocumenti da caricare
  208. request: i documenti vengono caricati via web
  209. utente: utente a cui associare il documento
  210. azienda: (perche? se l'utente deve essere gia' associato a un'azienda?)
  211. sede: (lo stesso, perche' passare la sede, se l'utente stesso dovrebbe avere gia' l'indicazione della sede)
  212. e comunque questi parametri servono solo per i log, che insomma, posso aggirarli con semplicita'
  213. descrizione: descrizione assegnata al documento
  214. amministratore: caricamente a mezzo di un amministratore
  215. """
  216. listaok = list()
  217. listanotok = list()
  218. listanotass = list()
  219. associato=False
  220. for singolodocumento in listadocumenti:
  221. print('singolodocumento',singolodocumento,descrizione)
  222. #risultato = upload_file(singolodocumento,utente)
  223. documento = Documento()
  224. documento.dataupload = datetime.datetime.now()
  225. documento.utente = utente
  226. documento.documento = singolodocumento.name
  227. #documento.storage = risultato
  228. documento.descrizione = descrizione
  229. documento.privato = _privato
  230. try:
  231. documento.save()
  232. setLog(8,azienda=azienda,sede=sede,utente=utente,documento=documento,amministratore=amministratore)
  233. #listaok.append(documento)
  234. print('record generato:',documento.id)
  235. associato=True
  236. except IntegrityError as ie:
  237. print("problema di integrita', il file esiste",ie)
  238. listanotok.append(documento)
  239. if associato:
  240. # se il record e' stato correttamente salvato, procede al caricamento del file.
  241. risultato=upload_file(singolodocumento,utente)
  242. documento.storage = risultato
  243. documento.save()
  244. listaok.append(documento)
  245. else:
  246. listanotass.append(documento)
  247. return (listaok,listanotok,listanotass)
  248. #file_indice: contiene l'elenco dei nominativi da gestire.
  249. def save_and_load_file_indice(request,fileindice,azienda=None,sede=None):
  250. """
  251. qui, oltre alla request, viene chiesto il nome del file indice
  252. il nome dell'azienda a cui si fa riferimento e la sua sede
  253. """
  254. print('nome indice caricato',fileindice.name)
  255. if azienda: print('azienda',azienda.nome)
  256. if sede: print('sede',sede.nome)
  257. file_memorizzato = upload_file_indice(request.FILES['indice'])
  258. fl_path = os.path.join(getConfig('DocPath'),getConfig('DocPathIndex'))
  259. risultato = None
  260. listaOk=list()
  261. listaNotOk=list()
  262. listaNotAss=list()
  263. with open(os.path.join(fl_path,file_memorizzato),'rb') as ind:
  264. risultato = ind.read()
  265. risultato = risultato.decode('utf-8',errors='replace')
  266. if isinstance(risultato,str):
  267. risultato = risultato.encode('utf8')
  268. with open(os.path.join(fl_path,''.join((file_memorizzato,'.cvtd'))),'wb') as ind:
  269. ind.write(risultato)
  270. print('una volta convertito, passiamo oltre')
  271. with open(os.path.join(fl_path,''.join((file_memorizzato,'.cvtd'))),'rt') as ind:
  272. spamreader = csv.reader(ind,delimiter=';')
  273. next(spamreader,None) #salta l'intestazione
  274. count = 0
  275. for sr in spamreader:
  276. salvare = False
  277. count +=1
  278. if count==1: continue
  279. print(count,'sr',sr,len(sr))
  280. if len(sr) >= 1 and len("".join(sr)) > 0: # la lunghezza del record segnala qualcosa
  281. print('record sr',sr)
  282. utente = None
  283. codicefiscale = sr[1].strip()
  284. print('codice fiscale',sr[1].strip().upper())
  285. try:
  286. utente = Utente.objects.get(codicefiscale=sr[1].strip().upper())
  287. listaNotAss.append({"nome":utente.nome,"codicefiscale":utente.codicefiscale,"errore":"già presente"})
  288. except Utente.DoesNotExist as dne:
  289. print('Utente non trovato')
  290. utente = Utente()
  291. if azienda: utente.azienda = azienda
  292. if sede: utente.sede = sede
  293. utente.nome = sr[0].strip().title()
  294. utente.codicefiscale=sr[1].strip().upper()
  295. for fmt in ('%d/%m/%y','%d/%m/%Y','%d-%m-%y','%d-%m-%Y'):
  296. try:
  297. data_convertita = datetime.datetime.strptime(sr[2],fmt)
  298. print('data convertita',data_convertita)
  299. utente.datanascita = data_convertita
  300. except ValueError as ve:
  301. print('errore con la data di nascita',ve)
  302. utente.luogonascita = sr[3].title()
  303. utente.mail = sr[4].strip().lower()
  304. # ricerca sede: se il codice estratto nella colonna corrisponde...
  305. tmp_sede = sr[5]
  306. lista_sede = azienda.sede_set.all()
  307. for ls in lista_sede:
  308. if tmp_sede == ls.identificativo:
  309. utente.sede = ls
  310. utente.cabiopassword = ls.cambiopassword
  311. utente.forzanuovapassword = ls.forzanuovapassword
  312. utente.otppassword = ls.otppassword
  313. else:
  314. utente.cabiopassword = azienda.cambiopassword
  315. utente.forzanuovapassword = azienda.forzanuovapassword
  316. utente.otppassword = azienda.otppassword
  317. utente.inserimento = datetime.datetime.today().strftime("%Y-%m-%d")
  318. utente.pin = str(randint(100000,999999))
  319. if len(utente.codicefiscale) == 16:
  320. utente.save()
  321. listaOk.append({"nome":utente.nome,"codicefiscale":utente.codicefiscale})
  322. else:
  323. print("Codice Fiscale NON valido o mancante")
  324. listaNotOk.append({"nome":utente.nome,"codicefiscale":utente.codicefiscale,"errore":"Codice Fiscale"})
  325. return (listaOk,listaNotOk,listaNotAss,count)
  326. def PrepareZipFile(listafile=[]):
  327. zip_path = os.path.join(settings.BASE_DIR,getConfig('DocZipFile'))
  328. print("zip_path:",zip_path)
  329. # verifica l'esistenza della directory
  330. try:
  331. os.mkdir(zip_path)
  332. except FileExistsError as fee:
  333. print(zip_path,"esistente")
  334. filename = ''.join((str(time.time()),'.zip'))
  335. with zipfile.ZipFile(os.path.join(zip_path,filename),'w') as zip:
  336. for lf in listafile:
  337. d = Documento.objects.get(pk=lf)
  338. file2zip = os.path.join(settings.BASE_DIR,getConfig('DocPath'),d.utente.azienda.partitaiva,d.utente.codicefiscale,d.storage)
  339. zip.write(file2zip,arcname=d.documento)
  340. print('path completa',file2zip)
  341. print('file completo',os.path.join(zip_path,filename))
  342. return (zip_path,filename)