source: main/waeup.kofa/trunk/src/waeup/kofa/browser/batchprocessing.txt @ 9310

Last change on this file since 9310 was 9310, checked in by Henrik Bettermann, 12 years ago

Batch processing of users does not work as expected. The test fails.

File size: 19.3 KB
Line 
1Batch processing via browser
2****************************
3
4Preliminaries:
5
6We define a function that looks up a form with several submit buttons
7for the one with a given value (this functionality is missing in
8zope.testbrowser):
9
10    >>> def lookup_submit_value(name, value, browser):
11    ...   """Find a button with a certain value."""
12    ...   for num in range(0, 100):
13    ...     try:
14    ...       button = browser.getControl(name=name, index=num)
15    ...       if button.value.endswith(value):
16    ...         return button
17    ...     except IndexError:
18    ...       break
19    ...   return None
20
21Create a site:
22
23    >>> from waeup.kofa.app import University
24    >>> getRootFolder()['app'] = University()
25
26Create a datacenter storage path:
27
28    >>> import os
29    >>> import tempfile
30    >>> dc_path = tempfile.mkdtemp()
31
32Log in:
33
34    >>> from zope.testbrowser.testing import Browser
35    >>> browser = Browser()
36    >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
37    >>> browser.handleErrors = False
38
39Set datacenter path and deselect moving old data:
40
41    >>> browser.open('http://localhost/app')
42    >>> browser.getLink('Data Center').click()
43    >>> browser.getLink('Edit settings').click()
44    >>> browser.getControl(name='newpath').value = dc_path
45    >>> browser.getControl(name='move').value = False
46    >>> browser.getControl(name='save').click()
47
48Set non-usable datacenter path:
49
50    >>> browser.getLink('Edit settings').click()
51    >>> browser.getControl(name='newpath').value = '/'
52    >>> browser.getControl(name='save').click()
53    >>> 'Given storage path cannot be used.' in browser.contents
54    True
55    >>> browser.getControl('Cancel').click()
56
57
58Batch processing faculties
59==========================
60
61Go to datacenter page:
62
63    >>> browser.open('http://localhost/app/datacenter')
64
65Prepare a CSV file for faculties:
66
67    >>> open('faculties.csv', 'wb').write(
68    ... """code,title,title_prefix
69    ... FAC1,Faculty 1,faculty
70    ... FAC2,Faculty 2,institute
71    ... FAC3,Faculty 3,school
72    ... """)
73
74Upload the file:
75
76    >>> import cStringIO
77    >>> browser.getLink('Upload data').click()
78    >>> filecontents = cStringIO.StringIO(
79    ...   open('faculties.csv', 'rb').read())
80    >>> filewidget = browser.getControl(name='uploadfile:file')
81    >>> filewidget.add_file(filecontents, 'text/plain', 'faculties.csv')
82    >>> browser.getControl(name='SUBMIT').click()
83
84Step 1: start batch processing:
85
86    >>> browser.getLink('Process data').click()
87    >>> button = lookup_submit_value(
88    ...   'select', 'faculties_zope.mgr.csv', browser)
89    >>> button.click()
90
91Step 2: select a processor and mode:
92
93    >>> importerselect = browser.getControl(name='importer')
94    >>> importerselect.displayOptions
95    ['AccessCodeBatch Processor', 'AccessCode Processor',
96    'Applicant Processor', 'Applicants Container Processor',
97    'CertificateCourse Processor', 'Certificate Processor',
98    'Course Processor', 'CourseTicket Processor',
99    'Department Processor', 'Faculty Processor',
100    'Hostel Processor',
101    'Student Payment Processor', 'Student Processor',
102    'StudentStudyCourse Processor (update only)',
103    'StudentStudyLevel Processor',
104    'User Processor',
105    'Verdict Processor (update only)']
106
107    >>> importerselect.getControl('Faculty Processor').selected = True
108
109    >>> modeselect = browser.getControl(name='mode')
110    >>> modeselect.options
111    ['create', 'update', 'remove']
112
113    >>> modeselect.getControl(value='create').selected = True
114    >>> browser.getControl('Proceed to step 3').click()
115
116Step 3: Fix headerlines
117
118We get informed that there are no problems with the current header:
119
120    >>> print browser.contents
121    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
122    ...
123    Header fields OK
124    ...
125
126The submit button is enabled:
127
128    >>> browser.getControl('Perform import').disabled
129    False
130
131    >>> browser.getControl('Perform import').click()
132
133Step 4: See import results
134
135The import was successful:
136
137    >>> print browser.contents
138    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
139    ...Successfully processed 3 rows...
140    ...Batch processing finished...
141    ...File:...faculties_zope.mgr.csv...
142
143We can grep the entries generated in logfile:
144
145    >>> browser.getControl('View processing log').click()
146    >>> print browser.contents
147    <!DOCTYPE ...
148    ...<h1>Logfile datacenter.log</h1>...
149
150    >>> browser.getControl(name='query').value = "zope.mgr"
151    >>> browser.getControl('Search').click()
152    >>> 'zope.mgr: Batch processing finished: OK' in browser.contents
153    True
154    >>> 'Mode: create' in browser.contents
155    True
156
157    >>> browser.getControl(name='query').value = "finished"
158    >>> browser.getControl('Search').click()
159    >>> 'zope.mgr: Batch processing finished: OK' in browser.contents
160    True
161    >>> 'Mode: create' in browser.contents
162    False
163
164
165Batch processing departments
166============================
167
168    >>> browser.open('http://localhost/app/datacenter')
169
170Prepare a CSV file for departments:
171
172    >>> open('departments.csv', 'wb').write(
173    ... """code,faculty_code,title,title_prefix
174    ... DEP1,FAC1,Department 1,department
175    ... DEP2,FAC2,Department 2,centre
176    ... """)
177
178Upload the file:
179
180    >>> import cStringIO
181    >>> browser.getLink('Upload data').click()
182    >>> filecontents = cStringIO.StringIO(
183    ...   open('departments.csv', 'rb').read())
184    >>> filewidget = browser.getControl(name='uploadfile:file')
185    >>> filewidget.add_file(filecontents, 'text/plain', 'departments.csv')
186    >>> browser.getControl(name='SUBMIT').click()
187
188Step 1: start batch processing:
189
190    >>> browser.getLink('Process data').click()
191    >>> button = lookup_submit_value(
192    ...   'select', 'departments_zope.mgr.csv', browser)
193    >>> button.click()
194
195Step 2: select a processor and mode:
196
197    >>> importerselect = browser.getControl(name='importer')
198    >>> importerselect.getControl('Department Processor').selected = True
199    >>> modeselect = browser.getControl(name='mode')
200    >>> modeselect.getControl(value='create').selected = True
201    >>> browser.getControl('Proceed to step 3').click()
202
203Step 3: Fix headerlines
204
205We get informed that there are no problems with the current header:
206
207    >>> print browser.contents
208    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
209    ...
210    Header fields OK
211    ...
212
213The submit button is enabled:
214
215    >>> browser.getControl('Perform import').disabled
216    False
217
218    >>> browser.getControl('Perform import').click()
219
220Step 4: See import results
221
222The import was successful:
223
224    >>> print browser.contents
225    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
226    ...Successfully processed 2 rows...
227    ...Batch processing finished...
228    ...File:...departments_zope.mgr.csv...
229
230Batch processing courses
231========================
232
233    >>> browser.open('http://localhost/app/datacenter')
234
235Prepare a CSV file for courses:
236
237    >>> open('courses.csv', 'wb').write(
238    ... """code,faculty_code,department_code,title,level,passmark,credits,semester
239    ... CRS1,FAC1,DEP1,Course 1,100,40,2,1
240    ... CRS2,FAC1,DEP1,Course 2,100,40,2,2
241    ... """)
242
243Upload the file:
244
245    >>> import cStringIO
246    >>> browser.getLink('Upload data').click()
247    >>> filecontents = cStringIO.StringIO(
248    ...   open('courses.csv', 'rb').read())
249    >>> filewidget = browser.getControl(name='uploadfile:file')
250    >>> filewidget.add_file(filecontents, 'text/plain', 'courses.csv')
251    >>> browser.getControl(name='SUBMIT').click()
252
253Step 1: start batch processing:
254
255    >>> browser.getLink('Process data').click()
256    >>> button = lookup_submit_value(
257    ...   'select', 'courses_zope.mgr.csv', browser)
258    >>> button.click()
259
260Step 2: select a processor and mode:
261
262    >>> importerselect = browser.getControl(name='importer')
263    >>> importerselect.getControl('Course Processor', index=1).selected = True
264    >>> modeselect = browser.getControl(name='mode')
265    >>> modeselect.getControl(value='create').selected = True
266    >>> browser.getControl('Proceed to step 3').click()
267
268Step 3: Fix headerlines
269
270We get informed that there are no problems with the current header:
271
272    >>> print browser.contents
273    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
274    ...
275    Header fields OK
276    ...
277
278The submit button is enabled:
279
280    >>> browser.getControl('Perform import').disabled
281    False
282
283    >>> browser.getControl('Perform import').click()
284
285Step 4: See import results
286
287The import was successful:
288
289    >>> print browser.contents
290    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
291    ...Successfully processed 2 rows...
292    ...Batch processing finished...
293    ...File:...courses_zope.mgr.csv...
294
295Batch processing certificates
296=============================
297
298    >>> browser.open('http://localhost/app/datacenter')
299
300Prepare a CSV file for certificates:
301
302    >>> open('certificates.csv', 'wb').write(
303    ... """code,faculty_code,department_code,title,study_mode,start_level,end_level,application_category
304    ... CERT1,FAC1,DEP1,Certificate 1,pg_ft,999,999,basic
305    ... CERT2,FAC1,DEP1,Certificate 2,ug_ft,200,300,cest
306    ... """)
307
308Upload the file:
309
310    >>> import cStringIO
311    >>> browser.getLink('Upload data').click()
312    >>> filecontents = cStringIO.StringIO(
313    ...   open('certificates.csv', 'rb').read())
314    >>> filewidget = browser.getControl(name='uploadfile:file')
315    >>> filewidget.add_file(filecontents, 'text/plain', 'certificates.csv')
316    >>> browser.getControl(name='SUBMIT').click()
317
318Step 1: start batch processing:
319
320    >>> browser.getLink('Process data').click()
321    >>> button = lookup_submit_value(
322    ...   'select', 'certificates_zope.mgr.csv', browser)
323    >>> button.click()
324
325
326Step 2: select a processor and mode:
327
328    >>> importerselect = browser.getControl(name='importer')
329    >>> importerselect.getControl('Certificate Processor').selected = True
330    >>> modeselect = browser.getControl(name='mode')
331    >>> modeselect.getControl(value='create').selected = True
332    >>> browser.getControl('Proceed to step 3').click()
333
334Step 3: Fix headerlines
335
336We get informed that there are no problems with the current header:
337
338    >>> print browser.contents
339    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
340    ...
341    Header fields OK
342    ...
343
344The submit button is enabled:
345
346    >>> browser.getControl('Perform import').disabled
347    False
348
349    >>> browser.getControl('Perform import').click()
350
351Step 4: See import results
352
353The import was successful:
354
355    >>> print browser.contents
356    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
357    ...Successfully processed 2 rows...
358    ...Batch processing finished...
359    ...File:...certificates_zope.mgr.csv...
360
361Batch processing certificate courses
362====================================
363
364    >>> browser.open('http://localhost/app/datacenter')
365
366Prepare a CSV file for certificate courses:
367
368    >>> open('mycertcourses.csv', 'wb').write(
369    ... """course,faculty_code,department_code,certificate_code,level,mandatory
370    ... CRS1,FAC1,DEP1,CERT1,100,True
371    ... CRS2,FAC1,DEP1,CERT1,100,True
372    ... """)
373
374Upload the file:
375
376    >>> import cStringIO
377    >>> browser.getLink('Upload data').click()
378    >>> filecontents = cStringIO.StringIO(
379    ...   open('mycertcourses.csv', 'rb').read())
380    >>> filewidget = browser.getControl(name='uploadfile:file')
381    >>> filewidget.add_file(filecontents, 'text/plain', 'mycertcourses.csv')
382    >>> browser.getControl(name='SUBMIT').click()
383
384Step 1: start batch processing:
385
386    >>> browser.getLink('Process data').click()
387    >>> button = lookup_submit_value(
388    ...   'select', 'mycertcourses_zope.mgr.csv', browser)
389    >>> button.click()
390
391Step 2: select a processor and mode:
392
393    >>> importerselect = browser.getControl(name='importer')
394    >>> importerselect.getControl('CertificateCourse Processor').selected = True
395    >>> modeselect = browser.getControl(name='mode')
396    >>> modeselect.getControl(value='create').selected = True
397    >>> browser.getControl('Proceed to step 3').click()
398
399Step 3: Fix headerlines
400
401We get informed that there are no problems with the current header:
402
403    >>> print browser.contents
404    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
405    ...
406    Header fields OK
407    ...
408
409The submit button is enabled:
410
411    >>> browser.getControl('Perform import').disabled
412    False
413
414    >>> browser.getControl('Perform import').click()
415
416Step 4: See import results
417
418The import was successful:
419
420    >>> print browser.contents
421    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
422    ...Successfully processed 2 rows...
423    ...Batch processing finished...
424    ...File:...mycertcourses_zope.mgr.csv...
425
426Batch processing users
427======================
428
429    >>> browser.open('http://localhost/app/datacenter')
430
431Prepare a CSV file for users:
432
433    >>> open('users.csv', 'wb').write(
434    ... """name,title,public_name,email,phone,roles
435    ... uli,Uli Fouquet,Chief Developer,uli@abc.de,+49-234-567,[]
436    ... henrik,Henrik Bettermann,Admin,henrik@abc.de,+49-234-567,"['waeup.PortalManager', 'waeup.ImportManager']"
437    ... """)
438
439Upload the file:
440
441    >>> import cStringIO
442    >>> browser.getLink('Upload data').click()
443    >>> filecontents = cStringIO.StringIO(
444    ...   open('users.csv', 'rb').read())
445    >>> filewidget = browser.getControl(name='uploadfile:file')
446    >>> filewidget.add_file(filecontents, 'text/plain', 'users.csv')
447    >>> browser.getControl(name='SUBMIT').click()
448
449Step 1: start batch processing:
450
451    >>> browser.getLink('Process data').click()
452    >>> button = lookup_submit_value(
453    ...   'select', 'users_zope.mgr.csv', browser)
454    >>> button.click()
455
456Step 2: select a processor and mode:
457
458    >>> importerselect = browser.getControl(name='importer')
459    >>> importerselect.getControl('User Processor').selected = True
460    >>> modeselect = browser.getControl(name='mode')
461    >>> modeselect.getControl(value='create').selected = True
462    >>> browser.getControl('Proceed to step 3').click()
463
464Step 3: Fix headerlines
465
466We get informed that there are no problems with the current header:
467
468    >>> print browser.contents
469    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
470    ...
471    Header fields OK
472    ...
473
474The submit button is enabled:
475
476    >>> browser.getControl('Perform import').disabled
477    False
478
479    >>> browser.getControl('Perform import').click()
480
481Step 4: See import results
482
483The import was successful:
484
485    >>> print browser.contents
486    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
487    ...Successfully processed 2 rows...
488    ...Batch processing finished...
489    ...File:...users_zope.mgr.csv...
490
491User henrik has got the global roles:
492
493   >>> henrik = getRootFolder()['app']['users']['henrik']
494   >>> henrik.roles
495   ['waeup.PortalManager', 'waeup.ImportManager']
496
497Pending files
498=============
499
500When an error occurs during an import, two files are generated: a CSV
501file with finished files and a CSV file with pending data. Both are
502stored in the appropriate subdirectories in datacenter. We try to
503create faculties, from which one already exists.
504
505Go to datacenter page:
506
507    >>> browser.open('http://localhost/app/datacenter')
508
509Prepare a CSV file for faculties:
510
511    >>> open('newfaculties.csv', 'wb').write(
512    ... """code,title,title_prefix
513    ... FAC1,Faculty 1,faculty
514    ... FAC4,Faculty 4,school
515    ... """)
516
517Upload the file:
518
519    >>> import cStringIO
520    >>> browser.getLink('Upload data').click()
521    >>> filecontents = cStringIO.StringIO(
522    ...   open('newfaculties.csv', 'rb').read())
523    >>> filewidget = browser.getControl(name='uploadfile:file')
524    >>> filewidget.add_file(filecontents, 'text/plain', 'newfaculties.csv')
525    >>> browser.getControl(name='SUBMIT').click()
526
527Since we now have a user with waeup.ImportManager role, an email has been sent:
528    >>> print browser.contents
529    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
530    ...
531    ...All import managers have been notified by email...
532    ...
533
534Step 1: start batch processing:
535
536    >>> browser.getLink('Process data').click()
537    >>> button = lookup_submit_value(
538    ...   'select', 'newfaculties_zope.mgr.csv', browser)
539    >>> button.click()
540
541Step 2: select a processor and mode:
542
543    >>> importerselect = browser.getControl(name='importer')
544    >>> importerselect.getControl('Faculty Processor').selected = True
545    >>> modeselect = browser.getControl(name='mode')
546    >>> modeselect.getControl(value='create').selected = True
547    >>> browser.getControl('Proceed to step 3').click()
548
549Step 3: Fix headerlines
550
551As there should be no problem with the headers, we can immediately
552perfom the import:
553
554    >>> browser.getControl('Perform import').click()
555
556One line could not be imported:
557
558    >>> print browser.contents
559    <!DOCTYPE html PUBLIC...
560    ...
561    ...Processing of 1 rows failed...
562    ...Successfully processed 1 rows...
563    ...
564
565Now there are two files as a result in datacenter storage's root and
566``finished`` dirs:
567
568    >>> pending_file = dc_path + '/newfaculties_zope.mgr.create.pending.csv'
569    >>> print open(pending_file).read()
570    title_prefix,code,title,--ERRORS--
571    faculty,FAC1,Faculty 1,This object already exists. Skipping.
572
573    >>> finished_file = dc_path + '/finished/newfaculties_zope.mgr.create.finished.csv'
574    >>> print open(finished_file).read()
575    title_prefix,code,title
576    school,FAC4,Faculty 4
577
578The finished-file contains the dataset we could import, while the
579pending file contains the dataset that failed, appended by an error
580message.
581
582
583Fixing the pending file
584-----------------------
585
586We 'edit' the pending file (setting code to ``FAC5`` and title
587appropriately, and removing the --ERROR-- column) and finish the
588import this way:
589
590    >>> open(dc_path + '/newfaculties_zope.mgr.create.pending.csv', 'wb').write(
591    ... """title_prefix,--IGNORE--,code,title
592    ... faculty,FAC5,Faculty 5
593    ... """)
594
595Step 1: start batch processing:
596
597    >>> browser.open('http://localhost/app/datacenter')
598    >>> browser.getLink('Process data').click()
599    >>> button = lookup_submit_value(
600    ...   'select', 'newfaculties_zope.mgr.create.pending.csv', browser)
601    >>> button.click()
602
603Step 2: select a processor and mode:
604
605    >>> importerselect = browser.getControl(name='importer')
606    >>> importerselect.getControl('Faculty Processor').selected = True
607    >>> modeselect = browser.getControl(name='mode')
608    >>> modeselect.getControl(value='create').selected = True
609    >>> browser.getControl('Proceed to step 3').click()
610
611Step 3/4: Fix headerlines and import:
612
613As there should be no problem with the headers, we can immediately
614perfom the import:
615
616    >>> browser.getControl('Perform import').click()
617
618This time everything should work:
619
620    >>> print browser.contents
621    <!DOCTYPE html PUBLIC...
622    ...
623    ...Successfully processed 1 rows...
624    ...
625
626    >>> sorted(os.listdir(dc_path))
627    ['deleted', 'finished', 'logs', 'unfinished']
628
629    >>> os.listdir(dc_path + '/unfinished')
630    []
631
632    >>> sorted(os.listdir(dc_path + '/finished'))
633    ['certificates_zope.mgr.create.finished.csv', ...,
634    'users_zope.mgr.create.finished.csv', 'users_zope.mgr.csv']
635
636Processed (finished) Files
637==========================
638
639    >>> browser.open('http://localhost/app/datacenter/processed')
640    >>> '<a href="download?filename=finished/certificates_zope.mgr.csv">' in browser.contents
641    True
642
643Log Files
644=========
645
646    >>> browser.open('http://localhost/app/datacenter/logs')
647    >>> 'datacenter.log' in browser.contents
648    True
649    >>> browser.getControl('Show', index=0).click()
650    >>> browser.getControl('Back', index=0).click()
651    >>> browser.getControl('Back to Data Center').click()
652    >>> 'Storage path:' in browser.contents
653    True
654
655
656Clean up:
657
658    >>> import shutil
659    >>> shutil.rmtree(dc_path)
Note: See TracBrowser for help on using the repository browser.