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

Last change on this file since 13645 was 13431, checked in by Henrik Bettermann, 9 years ago

Put maintenance button on DatacenterImportStep1.

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