source: main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt @ 17778

Last change on this file since 17778 was 17772, checked in by Henrik Bettermann, 6 months ago

Add ApplicantRefereeReportProcessor.

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