pièces jointes : gestion des pièces absentes dans SIGMA (patch)
[sigmawcs.git] / project / wcs / views.py
1 # -=- encoding: utf-8 -=-
2
3 import os
4 from simplejson import loads
5 import urllib2
6 import zipfile
7
8 from sigma_v1.models import Dossier
9 from sigma_v1.settings import PIECES_SUFFIXE as PIECES_SIGMA_SUFFIXE
10 from wcs.settings import PIECES_FIELDNAME, PIECES_SUFFIXE as PIECES_WCS_SUFFIXE
11 from wcs.settings import MOBILITE, FORMNAME, WCS_SIGMA_URL, WCS_SIGMA_USER, WCS_SIGMA_PASS
12
13 from lib import getCandidaturesJson
14 from models import JsonWcs2JsonSigma, JsonSigma2ObjectSigma
15
16 def importDossiersCandidaturesWcs(appel):
17 """Appel distant sur WCS et copie locale de tout le répertoire d'un appel
18 """
19 def retrieve(url, filename, force=True):
20 written = False
21 if not os.path.exists(filename) or force:
22 pagehandle = urllib2.urlopen(url)
23 f = file(filename, 'wb')
24 f.write(pagehandle.read())
25 f.close()
26 pagehandle.close()
27 written = True
28 return written
29
30 # conf
31 src = '%s/%s' % (WCS_SIGMA_URL, appel.wcs_form_name)
32 dst = 'docs/%s' % (appel.wcs_form_name)
33 dossierDir = 'data'
34 meta = [
35 'field-names.json',
36 'field-names.txt',
37 'last-run.log',
38 'liste-dossiers.json',
39 ]
40 erreurs = []
41
42 # local
43 if not os.path.exists(dst):
44 dstData = '%s/%s' % (dst, dossierDir)
45 os.makedirs(dstData) # mode 0777 ?
46
47 # accès WCS
48 passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
49 passman.add_password(None, WCS_SIGMA_URL, WCS_SIGMA_USER, WCS_SIGMA_PASS)
50 authhandler = urllib2.HTTPBasicAuthHandler(passman)
51 opener = urllib2.build_opener(authhandler)
52 urllib2.install_opener(opener)
53
54 # rapport : header
55 print '--------------------------------------------------'
56 print 'IMPORT WCS'
57 print 'Formulaire : %s' % (appel.wcs_form_name)
58 print '--------------------------------------------------'
59
60 # import meta
61 print 'Import des fichiers de méta-données sur le formulaire :'
62 os.chdir(dst)
63
64 nb_meta = len(meta)
65 nb_meta_done = 0
66 for filename in meta:
67 url = '%s/%s' % (src, filename)
68 rapport = '%s : %s' % ('meta', filename)
69 try:
70 retrieve(url, filename)
71 print rapport
72 nb_meta_done = nb_meta_done + 1
73 except urllib2.HTTPError:
74 erreurs.append(rapport)
75 print '--------------------------------------------------'
76
77 # import data
78 print 'Import des dossiers de candidature (json et pièces jointes) :'
79 f = open('liste-dossiers.json', 'r')
80 data = f.read()
81 f.close()
82 listjson = loads(data, encoding='utf-8')
83 listjson.sort()
84 os.chdir(dossierDir)
85
86 nb_json = len(listjson)
87 nb_json_done = 0
88 nb_json_imported = 0
89 nb_pieces = 0
90 for id, piece in PIECES_WCS_SUFFIXE.items():
91 if piece:
92 nb_pieces = nb_pieces + 1
93 nb_pieces = nb_pieces * nb_json
94 nb_pieces_done = 0
95 for filename in listjson:
96 # json
97 url = '%s/%s/%s' % (src, dossierDir, filename)
98 rapport = '%s : %s' % ('json', filename)
99 try:
100 imported = retrieve(url, filename, force=False)
101 if imported :
102 print rapport
103 nb_json_imported = nb_json_imported + 1
104 nb_json_done = nb_json_done + 1
105 except urllib2.HTTPError:
106 erreurs.append(rapport)
107
108 # pièces jointes
109 f = open(filename, 'r')
110 data = f.read()
111 f.close()
112 json = loads(data, encoding='utf-8')
113 for id, piece in PIECES_WCS_SUFFIXE.items():
114 if piece:
115 try:
116 pieceName = json[piece]
117 url = '%s/%s/%s' % (src, dossierDir, pieceName)
118 rapport = '* %s : %s' % (piece, pieceName)
119 retrieve(url, pieceName)
120 print rapport
121 nb_pieces_done = nb_pieces_done + 1
122 except KeyError, urllib2.HTTPError:
123 erreurs.append(rapport)
124 print ''
125 print '--------------------------------------------------'
126
127 if erreurs:
128 print '%d ERREURS' % (len(erreurs))
129 for erreur in erreurs:
130 print erreur
131 print '--------------------------------------------------'
132
133 # rapport : footer
134 print 'FIN IMPORT WCS'
135 print 'Méta traités : %d sur %d' % (nb_meta_done, nb_meta)
136 print 'Json traités : %d sur %d' % (nb_json_done, nb_json)
137 print 'Json importés : %d sur %d' % (nb_json_imported, nb_json)
138 print 'Pièces traitées : %d sur %d' % (nb_pieces_done, nb_pieces)
139 print '--------------------------------------------------'
140
141
142 #def getCandidaturesJsonWcs(request, appel):
143 # retourne la liste locale des json importés de WCS
144
145 #def exportSigmaData(request, appel):
146 # exporte dans la base de données SIGMA les données des candidatures json de WCS
147
148 def exportSigmaFiles(appel):
149 """Déplace les fichiers ZIP et PDF de la candidature à leur emplacement final sigma.
150 """
151
152 # conf
153 dossierDir = 'data'
154 src = 'docs/%s/%s' % (appel.wcs_form_name, dossierDir)
155 dst = 'docs/%s/export' % (appel.wcs_form_name)
156 dstZip = "docs/%s/candidatures" % (appel.wcs_form_name)
157 erreurs = []
158
159 if not os.path.exists(dst):
160 os.makedirs(dst) # mode 0777 ?
161 if not os.path.exists(dstZip):
162 os.mkdir(dstZip) # mode 0777 ?
163
164 mappingPiecesSuffixes = {}
165 for id, suffixe_wcs in PIECES_WCS_SUFFIXE.items():
166 if suffixe_wcs:
167 # nom champ json normalisé pour cette pièce
168 field = PIECES_FIELDNAME.get(id, '')
169 # suffixe SIGMA
170 suffixe_sigma = PIECES_SIGMA_SUFFIXE.get(id, '')
171 # pièces peuvent ne pas exister dans SIGMA
172 if not suffixe_sigma:
173 suffixe_sigma = suffixe_wcs
174 # mapping
175 mappingPiecesSuffixes[field] = (suffixe_wcs, suffixe_sigma)
176
177 # rapport : header
178 print '--------------------------------------------------'
179 print 'EXPORT DOSSIERS DE CANDIDATURE (FICHIERS) : SIGMAWCS => SIGMA'
180 print 'Formulaire : %s' % (appel.wcs_form_name)
181 print '--------------------------------------------------'
182
183 # création du répertoire local pour rsync
184 print "Création du répertoire local des dossiers de candidature (fichiers renommés) :"
185 exportCandidaturesPath = "%s/%d.zip" % (dstZip, MOBILITE)
186 archive = zipfile.ZipFile(exportCandidaturesPath, "w", zipfile.ZIP_STORED)
187
188 candidatures = getCandidaturesJson()
189 nb_cand = len(candidatures)
190 nb_spam = 0
191 nb_cand_done = 0
192
193 jj = JsonWcs2JsonSigma()
194 for candidature in candidatures :
195 if candidature['wcs_workflow_status'] == 'SPAM':
196 nb_spam = nb_spam + 1
197 else:
198 candidature = jj.mapper(candidature)
199 candidature = jj.cleanup(candidature)
200 candidature = jj.convert(candidature)
201 filename = candidature['wcs_json_filename']
202 basename = filename.rstrip('.json')
203 nb_cand_done = nb_cand_done + 1
204 print '%d : %s' % (nb_cand_done, basename)
205 # pièces jointes : renommage et copie
206 for field, mapping in mappingPiecesSuffixes.items():
207 nom_src = candidature[field]
208 suffixe_wcs = mapping[0]
209 suffixe_sigma = mapping[1]
210 nom_dst = nom_src.replace(suffixe_wcs, suffixe_sigma)
211 # pièces peuvent être facultatives dans WCS
212 if nom_src:
213 path_src = '%s/%s' % (src, nom_src)
214 path_dst = '%s/%s' % (dst, nom_dst)
215 fsrc = open(path_src, 'r')
216 fdst = file(path_dst, 'wb')
217 fdst.write(fsrc.read())
218 fdst.close()
219 fsrc.close()
220
221 # formulaire (.pdf) et dossier complet (.zip) : copie
222 extensions = ('.pdf', '.zip')
223 for ext in extensions:
224 nom_src = basename + ext
225 nom_dst = nom_src
226 path_src = '%s/%s' % (src, nom_src)
227 path_dst = '%s/%s' % (dst, nom_dst)
228 rapport = '* %s' % (path_src)
229 if os.path.exists(path_src):
230 fsrc = open(path_src, 'r')
231 fdst = file(path_dst, 'wb')
232 fdst.write(fsrc.read())
233 fdst.close()
234 fsrc.close()
235 # zip de tous les dossiers de candidature (zip des zips)
236 if ext == '.zip':
237 zipname = '%s-%s-%s.zip' % (candidature['sigma_personne_nom'].upper(), \
238 candidature['sigma_personne_prenom'].lower().title(), \
239 candidature['sigma_dossier_m_discipline'])
240 archive.write(path_src, zipname)
241 print rapport
242 else:
243 erreurs.append(rapport)
244 print ''
245 print '--------------------------------------------------'
246 archive.close()
247
248 # déplacement de l'archive sur le serveur
249 # attention : archive plus créée (répertoire rsyncé)
250 # todo : avec fabric
251
252 # extraction de l'archive dans les sources SIGMA
253 # attention : archive plus créée (répertoire rsyncé)
254 # todo :
255 # from wcs.conf import MOBILITE
256 # project/modules/candidatures/docs/%s/ % (MOBILITE)
257
258 # rapport : erreurs
259 if erreurs:
260 print '%d ERREURS' % (len(erreurs))
261 for erreur in erreurs:
262 print erreur
263 print '--------------------------------------------------'
264
265 # rapport : footer
266 print 'FIN EXPORT DOSSIERS'
267 print 'Candidatures : %d' % (nb_cand)
268 print 'Spams : %d sur %d' % (nb_spam, nb_cand)
269 print 'Json traités : %d sur %d' % (nb_cand_done, nb_cand)
270 # print 'PDF traités : %d sur %d' % (nb_pdf_done, nb_cand_done)
271 # print 'ZIP traités : %d sur %d' % (nb_zip_done, nb_cand_done)
272 print '--------------------------------------------------'
273
274 # MAIN
275 if __name__ == "__main__":
276 """
277 bin/django shell # python manage.py shell
278 >>> cd wcs
279 >>> run views.py
280 """
281 # candidats déjà dans SIGMA pour cet appel
282 existants = set()
283 try:
284 dossiers = Dossier.objects.filter(mobilite=MOBILITE)
285 except:
286 dossiers = Dossier.objects.none()
287 for dossier in dossiers:
288 existants.add(dossier.personne.email)
289 nb_existants = len(existants)
290
291 # json WCS
292 candidatures = getCandidaturesJson()
293 nombre = len(candidatures)
294 spams = 0
295 traites = 0
296
297 # rapport : header
298 print 'IMPORT CANDIDATURES : WCS => json => SIGMA'
299 print 'Formulaire : %s' % FORMNAME
300 print '--------------------------------------------------'
301 print 'Nombre à traiter = %d' % (nombre)
302 print '--------------------------------------------------'
303 # IMPORT
304 jj = JsonWcs2JsonSigma()
305 jo = JsonSigma2ObjectSigma()
306 for candidature in candidatures :
307 candidature = jj.mapper(candidature)
308 print 'WCS %s : en cours...' % candidature['wcs_num_dossier']
309 if candidature['wcs_workflow_status'] == 'SPAM':
310 spams = spams + 1
311 elif candidature['sigma_personne_email'] in existants:
312 print 'existant : %s' % (candidature['sigma_personne_email'])
313 else :
314 # json
315 candidature = jj.cleanup(candidature)
316 candidature = jj.convert(candidature)
317 # objets SIGMA
318 p = jo.createPersonne(candidature)
319 d = jo.createDossier(candidature, p)
320 do = jo.createDossierOrigine(candidature, d)
321 da = jo.createDossierAccueil(candidature, d)
322 dm = jo.createDossierMobilite(candidature, d)
323 pieces = jo.createDossierPieces(candidature, d)
324 traites = traites + 1
325 print '%d - %s' % (traites, p)
326
327 # rapport : footer
328 print '--------------------------------------------------'
329 print 'Total existants = %d sur %d' % (nb_existants, nombre)
330 print 'Total spams = %d sur %d' % (spams, nombre)
331 print 'Total traités = %d sur %d' % (traites, nombre)
332 print 'Total = %d sur %d' % (nb_existants + spams + traites, nombre)
333 print '--------------------------------------------------'