Ignore:
Timestamp:
13 Nov 2014, 13:21:59 (10 years ago)
Author:
Henrik Bettermann
Message:

Enucleation. Keep only the portal's framework. Remove university, students, applicants, hostels and accesscodes modules.

Location:
main/waeup.kofa/branches/henrik-regista/src/waeup/kofa
Files:
21 deleted
33 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/app.py

    r11477 r11947  
    5151        """Setup some hard-wired components.
    5252
    53         Create local datacenter, containers for users, students and
     53        Create local datacenter, containers for users and
    5454        the like.
    5555        """
    56         from waeup.kofa.students.container import StudentsContainer
    57         from waeup.kofa.hostels.container import HostelsContainer
    5856
    5957        self['users'] = UsersContainer()
    6058        self['datacenter'] = DataCenter()
    61         self['students'] = StudentsContainer()
    6259        self['configuration'] = ConfigurationContainer()
    63         self['hostels'] = HostelsContainer()
    6460        self['mandates'] = MandatesContainer()
    6561        self._createPlugins()
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/app.txt

    r7819 r11947  
    5858    u'Sample University'
    5959
    60     >>> myuniversity['faculties']
    61     <waeup.kofa.university.facultiescontainer.FacultiesContainer object at 0x...>
    62 
    63   >>> myuniversity['students']
    64   <waeup.kofa.students.container.StudentsContainer object at 0x...>
    65 
    6660  >>> myuniversity['users']
    6761  <waeup.kofa.userscontainer.UsersContainer object at 0x...>
     
    7367  <waeup.kofa.configuration.ConfigurationContainer object at 0x...>
    7468
    75 We can export universities. For this we lookup an appropriate exporter
    76 first::
    77 
    78   >>> from waeup.kofa.interfaces import IKofaExporter
    79   >>> exporter = IKofaExporter(myuniversity)
    80   >>> exporter
    81   <waeup.kofa.utils.importexport.Exporter object at 0x...>
    82 
    83 Now we can trigger the export::
    84 
    85   >>> exporter.export()
    86   <cStringIO.StringO object at 0x...>
    87 
    88 We can also get an XML representation as file. If we do not provide a
    89 filepath, we will get an instance of `cStringIO.StringIO`, i.e. a
    90 memory file::
    91 
    92   >>> from waeup.kofa.interfaces import IKofaXMLExporter
    93   >>> exporter = IKofaXMLExporter(myuniversity)
    94   >>> f = exporter.export()
    95   >>> f
    96   <cStringIO.StringO object at 0x...>
    97 
    98   >>> print f.read()
    99   <?xml version="1.0" encoding="utf-8" ?>
    100   <pickle>
    101     <initialized_object id="...">
    102   ...
    103   </pickle>
    10469
    10570Kofa plugins
     
    11681   >>> from zope.component import getAdapters, getUtilitiesFor
    11782   >>> sorted(list(getUtilitiesFor(IKofaPluggable)))
    118    [(u'accesscodes', <waeup.kofa.accesscodes...AccessCodePlugin ...)]
     83   [(u'mandates', <waeup.kofa.mandates.container.MandatesPlugin ...)]
    11984
    12085
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/authentication.py

    r10055 r11947  
    388388def handle_account_added(account, event):
    389389    """When an account is added, the local owner role and the global
    390     AcademicsOfficer role must be set.
     390    ProductsOfficer role must be set.
    391391    """
    392392    # We set the local Owner role
     
    394394    role_manager_account.assignRoleToPrincipal(
    395395        'waeup.local.Owner', account.name)
    396     # We set the global AcademicsOfficer role
     396    # We set the global ProductsOfficer role
    397397    site = grok.getSite()
    398398    role_manager_site = IPrincipalRoleManager(site)
    399399    role_manager_site.assignRoleToPrincipal(
    400         'waeup.AcademicsOfficer', account.name)
     400        'waeup.ProductsOfficer', account.name)
    401401    # Finally we have to notify the user account that the local role
    402402    # of the same object has changed
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/authentication.txt

    r9308 r11947  
    5151  {'waeup.local.Owner': [<waeup.kofa.authentication.Account object at 0x...>]}
    5252
    53 User  automatically get the global AcademicsOfficer role:
     53User  automatically get the global ProductsOfficer role:
    5454
    5555  >>> alice.getSiteRolesForPrincipal()
    56   ['waeup.ManageDataCenter', 'waeup.AcademicsOfficer']
     56  ['waeup.ManageDataCenter', 'waeup.ProductsOfficer']
    5757
    5858We can tell an account, that Alice got some role for another object:
     
    8888stored objects are removed. Furthermore this subscriber reads the
    8989internal local roles table.
    90 
    91 We create a faculty and grant Bob a local role:
    92 
    93    >>> from zope.securitypolicy.interfaces import IPrincipalRoleManager
    94    >>> from waeup.kofa.university.faculty import Faculty
    95    >>> faculty = Faculty()
    96    >>> root['app']['bobs_fac'] = faculty
    97    >>> role_manager = IPrincipalRoleManager(faculty)
    98    >>> role_manager.assignRoleToPrincipal(
    99    ...    'waeup.PortalManager', 'bob')
    100 
    101 We notify the machinery about that fact:
    102 
    103    >>> notify(LocalRoleSetEvent(faculty, 'waeup.PortalManager', 'bob',
    104    ...                          granted=True))
    105    >>> bob = root['app']['users']['bob']
    106    >>> bob.getLocalRoles()
    107    {'waeup.PortalManager': [<waeup.kofa...Faculty object at 0x...>]}
    108 
    109 When we delete the faculty from ZODB, also Bobs roles are modified:
    110 
    111    >>> del root['app']['bobs_fac']
    112    >>> bob.getLocalRoles()
    113    {'waeup.local.Owner': [<waeup.kofa.authentication.Account object at 0x...>]}
    114 
    115 If one notifies the machinery of a local role removal for an object
    116 that cannot have local roles, this will cause no trouble:
    117 
    118    >>> mycontext = None #object()
    119    >>> notify(LocalRoleSetEvent(
    120    ...   mycontext, 'waeup.PortalManager', 'bob', granted=False
    121    ... )) is None
    122    True
    123 
    124 When an account get deleted, also the local roles of the owner get
    125 removed. Let's setup a local role for `alice`:
    126 
    127    >>> faculty = Faculty()
    128    >>> root['app']['alice_fac'] = faculty
    129    >>> role_manager = IPrincipalRoleManager(faculty)
    130    >>> role_manager.assignRoleToPrincipal(
    131    ...    'waeup.PortalManager', 'alice')
    132    >>> notify(LocalRoleSetEvent(faculty, 'waeup.PortalManager', 'alice',
    133    ...                          granted=True))
    134 
    135 The local role is set now:
    136 
    137    >>> from zope.securitypolicy.interfaces import IPrincipalRoleMap
    138    >>> IPrincipalRoleMap(faculty).getPrincipalsAndRoles()
    139    [('waeup.PortalManager', 'alice', PermissionSetting: Allow)]
    140 
    141 But when we delete Alices account from ZODB:
    142 
    143    >>> del root['app']['users']['alice']
    144    >>> IPrincipalRoleMap(faculty).getPrincipalsAndRoles()
    145    []
    146 
    147 the local role has gone and also the site roles have been removed:
    148 
    149    >>> prm = IPrincipalRoleManager(root['app'])
    150    >>> [x[0] for x in prm.getRolesForPrincipal('alice')
    151    ...      if x[0].startswith('waeup.')]
    152    []
    15390
    15491
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/batchprocessing.txt

    r11699 r11947  
    5858
    5959
    60 Batch processing faculties
    61 ==========================
    62 
    63 Go to datacenter page:
    64 
    65     >>> browser.open('http://localhost/app/datacenter')
    66 
    67 Prepare 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 
    76 Upload 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 
    86 Step 1: start batch processing:
    87 
    88     >>> browser.getLink('Process data').click()
    89     >>> button = lookup_submit_value(
    90     ...   'select', 'faculties_zope.mgr.csv', browser)
    91     >>> button.click()
    92 
    93 Step 2: select a processor and mode:
    94 
    95     >>> importerselect = browser.getControl(name='importer')
    96     >>> importerselect.displayOptions
    97     ['AccessCodeBatch Processor', 'AccessCode Processor',
    98     'Applicant Processor', 'ApplicantsContainer Processor',
    99     'CertificateCourse Processor', 'Certificate Processor',
    100     'Course Processor',
    101     'CourseTicket Processor',
    102     'Department Processor', 'Faculty Processor',
    103     'Hostel Processor',
    104     'StudentOnlinePayment Processor', 'Student Processor',
    105     'StudentStudyCourse Processor (update only)',
    106     'StudentStudyLevel Processor',
    107     'User Processor',
    108     'Verdict Processor (special processor, update only)']
    109 
    110     >>> importerselect.getControl('Faculty Processor').selected = True
    111 
    112     >>> modeselect = browser.getControl(name='mode')
    113     >>> modeselect.options
    114     ['create', 'update', 'remove']
    115 
    116     >>> modeselect.getControl(value='create').selected = True
    117     >>> browser.getControl('Proceed to step 3').click()
    118 
    119 Step 3: Fix headerlines
    120 
    121 We get informed that there are no problems with the current header:
    122 
    123     >>> print browser.contents
    124     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    125     ...
    126     Header fields OK
    127     ...
    128 
    129 The submit button is enabled:
    130 
    131     >>> browser.getControl('Perform import').disabled
    132     False
    133 
    134     >>> browser.getControl('Perform import').click()
    135 
    136 Step 4: See import results
    137 
    138 The import was successful:
    139 
    140     >>> print browser.contents
    141     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    142     ...Successfully processed 3 rows...
    143     ...Batch processing finished...
    144     ...File:...faculties_zope.mgr.csv...
    145 
    146 We can grep the entries generated in logfile:
    147 
    148     >>> browser.open('http://localhost/app/datacenter/logs')
    149     >>> browser.getControl('Show', index=0).click()
    150     >>> print browser.contents
    151     <!DOCTYPE ...
    152     ...<h1 class="kofa-content-label">Logfile datacenter.log</h1>...
    153 
    154     >>> browser.getControl(name='query').value = "zope.mgr"
    155     >>> browser.getControl('Search').click()
    156     >>> 'zope.mgr - processed' in browser.contents
    157     True
    158 
    159 
    160 Batch processing departments
    161 ============================
    162 
    163     >>> browser.open('http://localhost/app/datacenter')
    164 
    165 Prepare a CSV file for departments:
    166 
    167     >>> open('departments.csv', 'wb').write(
    168     ... """code,faculty_code,title,title_prefix
    169     ... DEP1,FAC1,Department 1,department
    170     ... DEP2,FAC2,Department 2,centre
    171     ... """)
    172 
    173 Upload the file:
    174 
    175     >>> import cStringIO
    176     >>> browser.getLink('Upload data').click()
    177     >>> filecontents = cStringIO.StringIO(
    178     ...   open('departments.csv', 'rb').read())
    179     >>> filewidget = browser.getControl(name='uploadfile:file')
    180     >>> filewidget.add_file(filecontents, 'text/plain', 'departments.csv')
    181     >>> browser.getControl(name='SUBMIT').click()
    182 
    183 Step 1: start batch processing:
    184 
    185     >>> browser.getLink('Process data').click()
    186     >>> button = lookup_submit_value(
    187     ...   'select', 'departments_zope.mgr.csv', browser)
    188     >>> button.click()
    189 
    190 Step 2: select a processor and mode:
    191 
    192     >>> importerselect = browser.getControl(name='importer')
    193     >>> importerselect.getControl('Department Processor').selected = True
    194     >>> modeselect = browser.getControl(name='mode')
    195     >>> modeselect.getControl(value='create').selected = True
    196     >>> browser.getControl('Proceed to step 3').click()
    197 
    198 Step 3: Fix headerlines
    199 
    200 We get informed that there are no problems with the current header:
    201 
    202     >>> print browser.contents
    203     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    204     ...
    205     Header fields OK
    206     ...
    207 
    208 The submit button is enabled:
    209 
    210     >>> browser.getControl('Perform import').disabled
    211     False
    212 
    213     >>> browser.getControl('Perform import').click()
    214 
    215 Step 4: See import results
    216 
    217 The import was successful:
    218 
    219     >>> print browser.contents
    220     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    221     ...Successfully processed 2 rows...
    222     ...Batch processing finished...
    223     ...File:...departments_zope.mgr.csv...
    224 
    225 Batch processing courses
    226 ========================
    227 
    228     >>> browser.open('http://localhost/app/datacenter')
    229 
    230 Prepare a CSV file for courses:
    231 
    232     >>> open('courses.csv', 'wb').write(
    233     ... """code,faculty_code,department_code,title,level,passmark,credits,semester
    234     ... CRS1,FAC1,DEP1,Course 1,100,40,2,1
    235     ... CRS2,FAC1,DEP1,Course 2,100,40,2,2
    236     ... """)
    237 
    238 Upload the file:
    239 
    240     >>> import cStringIO
    241     >>> browser.getLink('Upload data').click()
    242     >>> filecontents = cStringIO.StringIO(
    243     ...   open('courses.csv', 'rb').read())
    244     >>> filewidget = browser.getControl(name='uploadfile:file')
    245     >>> filewidget.add_file(filecontents, 'text/plain', 'courses.csv')
    246     >>> browser.getControl(name='SUBMIT').click()
    247 
    248 Step 1: start batch processing:
    249 
    250     >>> browser.getLink('Process data').click()
    251     >>> button = lookup_submit_value(
    252     ...   'select', 'courses_zope.mgr.csv', browser)
    253     >>> button.click()
    254 
    255 Step 2: select a processor and mode:
    256 
    257     >>> importerselect = browser.getControl(name='importer')
    258     >>> importerselect.getControl('Course Processor', index=1).selected = True
    259     >>> modeselect = browser.getControl(name='mode')
    260     >>> modeselect.getControl(value='create').selected = True
    261     >>> browser.getControl('Proceed to step 3').click()
    262 
    263 Step 3: Fix headerlines
    264 
    265 We get informed that there are no problems with the current header:
    266 
    267     >>> print browser.contents
    268     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    269     ...
    270     Header fields OK
    271     ...
    272 
    273 The submit button is enabled:
    274 
    275     >>> browser.getControl('Perform import').disabled
    276     False
    277 
    278     >>> browser.getControl('Perform import').click()
    279 
    280 Step 4: See import results
    281 
    282 The import was successful:
    283 
    284     >>> print browser.contents
    285     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    286     ...Successfully processed 2 rows...
    287     ...Batch processing finished...
    288     ...File:...courses_zope.mgr.csv...
    289 
    290 Batch processing certificates
    291 =============================
    292 
    293     >>> browser.open('http://localhost/app/datacenter')
    294 
    295 Prepare a CSV file for certificates:
    296 
    297     >>> open('certificates.csv', 'wb').write(
    298     ... """code,faculty_code,department_code,title,study_mode,start_level,end_level,application_category
    299     ... CERT1,FAC1,DEP1,Certificate 1,pg_ft,999,999,basic
    300     ... CERT2,FAC1,DEP1,Certificate 2,ug_ft,200,300,cest
    301     ... """)
    302 
    303 Upload the file:
    304 
    305     >>> import cStringIO
    306     >>> browser.getLink('Upload data').click()
    307     >>> filecontents = cStringIO.StringIO(
    308     ...   open('certificates.csv', 'rb').read())
    309     >>> filewidget = browser.getControl(name='uploadfile:file')
    310     >>> filewidget.add_file(filecontents, 'text/plain', 'certificates.csv')
    311     >>> browser.getControl(name='SUBMIT').click()
    312 
    313 Step 1: start batch processing:
    314 
    315     >>> browser.getLink('Process data').click()
    316     >>> button = lookup_submit_value(
    317     ...   'select', 'certificates_zope.mgr.csv', browser)
    318     >>> button.click()
    319 
    320 
    321 Step 2: select a processor and mode:
    322 
    323     >>> importerselect = browser.getControl(name='importer')
    324     >>> importerselect.getControl('Certificate Processor').selected = True
    325     >>> modeselect = browser.getControl(name='mode')
    326     >>> modeselect.getControl(value='create').selected = True
    327     >>> browser.getControl('Proceed to step 3').click()
    328 
    329 Step 3: Fix headerlines
    330 
    331 We get informed that there are no problems with the current header:
    332 
    333     >>> print browser.contents
    334     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    335     ...
    336     Header fields OK
    337     ...
    338 
    339 The submit button is enabled:
    340 
    341     >>> browser.getControl('Perform import').disabled
    342     False
    343 
    344     >>> browser.getControl('Perform import').click()
    345 
    346 Step 4: See import results
    347 
    348 The import was successful:
    349 
    350     >>> print browser.contents
    351     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    352     ...Successfully processed 2 rows...
    353     ...Batch processing finished...
    354     ...File:...certificates_zope.mgr.csv...
    355 
    356 Batch processing certificate courses
    357 ====================================
    358 
    359     >>> browser.open('http://localhost/app/datacenter')
    360 
    361 Prepare a CSV file for certificate courses:
    362 
    363     >>> open('mycertcourses.csv', 'wb').write(
    364     ... """course,faculty_code,department_code,certificate_code,level,mandatory
    365     ... CRS1,FAC1,DEP1,CERT1,100,True
    366     ... CRS2,FAC1,DEP1,CERT1,100,True
    367     ... """)
    368 
    369 Upload the file:
    370 
    371     >>> import cStringIO
    372     >>> browser.getLink('Upload data').click()
    373     >>> filecontents = cStringIO.StringIO(
    374     ...   open('mycertcourses.csv', 'rb').read())
    375     >>> filewidget = browser.getControl(name='uploadfile:file')
    376     >>> filewidget.add_file(filecontents, 'text/plain', 'mycertcourses.csv')
    377     >>> browser.getControl(name='SUBMIT').click()
    378 
    379 Step 1: start batch processing:
    380 
    381     >>> browser.getLink('Process data').click()
    382     >>> button = lookup_submit_value(
    383     ...   'select', 'mycertcourses_zope.mgr.csv', browser)
    384     >>> button.click()
    385 
    386 Step 2: select a processor and mode:
    387 
    388     >>> importerselect = browser.getControl(name='importer')
    389     >>> importerselect.getControl('CertificateCourse Processor').selected = True
    390     >>> modeselect = browser.getControl(name='mode')
    391     >>> modeselect.getControl(value='create').selected = True
    392     >>> browser.getControl('Proceed to step 3').click()
    393 
    394 Step 3: Fix headerlines
    395 
    396 We get informed that there are no problems with the current header:
    397 
    398     >>> print browser.contents
    399     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    400     ...
    401     Header fields OK
    402     ...
    403 
    404 The submit button is enabled:
    405 
    406     >>> browser.getControl('Perform import').disabled
    407     False
    408 
    409     >>> browser.getControl('Perform import').click()
    410 
    411 Step 4: See import results
    412 
    413 The import was successful:
    414 
    415     >>> print browser.contents
    416     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    417     ...Successfully processed 2 rows...
    418     ...Batch processing finished...
    419     ...File:...mycertcourses_zope.mgr.csv...
    420 
    42160Batch processing users
    42261======================
     
    488127   >>> henrik = getRootFolder()['app']['users']['henrik']
    489128   >>> henrik.roles
    490    ['waeup.PortalManager', 'waeup.AcademicsOfficer', 'waeup.ImportManager']
     129   ['waeup.ProductsOfficer', 'waeup.PortalManager', 'waeup.ImportManager']
    491130
    492131Pending files
     
    502141    >>> browser.open('http://localhost/app/datacenter')
    503142
    504 Prepare a CSV file for faculties:
    505 
    506     >>> open('newfaculties.csv', 'wb').write(
    507     ... """code,title,title_prefix
    508     ... FAC1,Faculty 1,faculty
    509     ... FAC4,Faculty 4,school
     143Prepare a CSV file for users:
     144
     145    >>> open('newusers.csv', 'wb').write(
     146    ... """name,title,public_name,email,phone,roles
     147    ... isouaba,Issoufou Abba Moussa,Chief Developer,isouaba@abc.de,+49-234-567,[]
     148    ... henrik,Henrik Bettermann,Admin,henrik@abc.de,+49-234-567,"['waeup.PortalManager', 'waeup.ImportManager']"
    510149    ... """)
    511150
     
    515154    >>> browser.getLink('Upload data').click()
    516155    >>> filecontents = cStringIO.StringIO(
    517     ...   open('newfaculties.csv', 'rb').read())
     156    ...   open('newusers.csv', 'rb').read())
    518157    >>> filewidget = browser.getControl(name='uploadfile:file')
    519     >>> filewidget.add_file(filecontents, 'text/plain', 'newfaculties.csv')
     158    >>> filewidget.add_file(filecontents, 'text/plain', 'newusers.csv')
    520159    >>> browser.getControl(name='SUBMIT').click()
    521160
     
    531170    >>> browser.getLink('Process data').click()
    532171    >>> button = lookup_submit_value(
    533     ...   'select', 'newfaculties_zope.mgr.csv', browser)
     172    ...   'select', 'newusers_zope.mgr.csv', browser)
    534173    >>> button.click()
    535174
     
    537176
    538177    >>> importerselect = browser.getControl(name='importer')
    539     >>> importerselect.getControl('Faculty Processor').selected = True
     178    >>> importerselect.getControl('User Processor').selected = True
    540179    >>> modeselect = browser.getControl(name='mode')
    541180    >>> modeselect.getControl(value='create').selected = True
     
    561200``finished`` dirs:
    562201
    563     >>> pending_file = dc_path + '/newfaculties_zope.mgr.create.pending.csv'
     202    >>> pending_file = dc_path + '/newusers_zope.mgr.create.pending.csv'
    564203    >>> print open(pending_file).read()
    565     title_prefix,code,title,--ERRORS--
    566     faculty,FAC1,Faculty 1,This object already exists. Skipping.
    567 
    568     >>> finished_file = dc_path + '/finished/newfaculties_zope.mgr.create.finished.csv'
     204    name,roles,title,public_name,phone,email,--ERRORS--
     205    henrik,"['waeup.PortalManager', 'waeup.ImportManager']",Henrik Bettermann,Admin,+49-234-567,henrik@abc.de,This object already exists. Skipping.
     206
     207    >>> finished_file = dc_path + '/finished/newusers_zope.mgr.create.finished.csv'
    569208    >>> print open(finished_file).read()
    570     title_prefix,code,title
    571     school,FAC4,Faculty 4
     209    name,roles,title,public_name,phone,email
     210    isouaba,[],Issoufou Abba Moussa,Chief Developer,+49-234-567,isouaba@abc.de
    572211
    573212The finished-file contains the dataset we could import, while the
     
    583222import this way:
    584223
    585     >>> open(dc_path + '/newfaculties_zope.mgr.create.pending.csv', 'wb').write(
    586     ... """title_prefix,--IGNORE--,code,title
    587     ... faculty,FAC5,Faculty 5
     224    >>> open(dc_path + '/newusers_zope.mgr.create.pending.csv', 'wb').write(
     225    ... """name,title,public_name,email,phone,roles
     226    ... gbenga,Jason Bamidele,Chief Developer,gbenga@abc.de,+49-234-567,[]
    588227    ... """)
    589228
     
    593232    >>> browser.getLink('Process data').click()
    594233    >>> button = lookup_submit_value(
    595     ...   'select', 'newfaculties_zope.mgr.create.pending.csv', browser)
     234    ...   'select', 'newusers_zope.mgr.create.pending.csv', browser)
    596235    >>> button.click()
    597236
     
    599238
    600239    >>> importerselect = browser.getControl(name='importer')
    601     >>> importerselect.getControl('Faculty Processor').selected = True
     240    >>> importerselect.getControl('User Processor').selected = True
    602241    >>> modeselect = browser.getControl(name='mode')
    603242    >>> modeselect.getControl(value='create').selected = True
     
    626265
    627266    >>> sorted(os.listdir(dc_path + '/finished'))
    628     ['certificates_zope.mgr.create.finished.csv', ...,
    629     'users_zope.mgr.create.finished.csv', 'users_zope.mgr.csv']
     267    ['newusers_zope.mgr.create.finished.csv', 'newusers_zope.mgr.csv', 'users_zope.mgr.create.finished.csv', 'users_zope.mgr.csv']
    630268
    631269Processed (finished) Files
     
    633271
    634272    >>> browser.open('http://localhost/app/datacenter/processed')
    635     >>> 'download?filename=finished/certificates_zope.mgr.create.finished.csv' in browser.contents
     273    >>> 'download?filename=finished/users_zope.mgr.create.finished.csv' in browser.contents
    636274    True
    637275
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/breadcrumbs.py

    r10655 r11947  
    2828from waeup.kofa.browser.interfaces import (
    2929    IBreadcrumb, IBreadcrumbIgnorable, IBreadcrumbContainer, IKofaObject,
    30     IUniversity, IFacultiesContainer, IUsersContainer, IDataCenter, IFaculty,
    31     IDepartment, ICourse, ICertificate, ICoursesContainer, ICertificateCourse,
    32     ICertificatesContainer
     30    IUniversity, IUsersContainer, IDataCenter,
    3331    )
    3432from waeup.kofa.reports import IReportsContainer
     
    114112        return (self.context, 'administration')
    115113
    116 class FacultiesContainerBreadcrumb(Breadcrumb):
    117     """A breadcrumb for faculty containers.
    118     """
    119     grok.context(IFacultiesContainer)
    120     title = _(u'Academics')
    121 
    122114class AdministrationBreadcrumb(Breadcrumb):
    123115    """A breadcrumb for administration areas of University instances.
     
    174166    title = _(u'Student Data Exports')
    175167    target = None
    176 
    177 class FacultyBreadcrumb(Breadcrumb):
    178     """A breadcrumb for faculties.
    179     """
    180     grok.context(IFaculty)
    181 
    182     @property
    183     def title(self):
    184         return self.context.longtitle
    185 
    186 class DepartmentBreadcrumb(FacultyBreadcrumb):
    187     """A breadcrumb for departments.
    188     """
    189     grok.context(IDepartment)
    190 
    191 class CourseBreadcrumb(FacultyBreadcrumb):
    192     """A breadcrumb for courses.
    193     """
    194     grok.context(ICourse)
    195 
    196 class CertificateBreadcrumb(FacultyBreadcrumb):
    197     """A breadcrumb for certificates.
    198     """
    199     grok.context(ICertificate)
    200 
    201 class CoursesContainerBreadcrumb(Breadcrumb):
    202     """ We don't want course container breadcrumbs.
    203     """
    204     grok.context(ICoursesContainer)
    205     grok.implements(IBreadcrumbIgnorable)
    206 
    207 class CertificatesContainerBreadcrumb(Breadcrumb):
    208     """ We don't want course container breadcrumbs.
    209     """
    210     grok.context(ICertificatesContainer)
    211     grok.implements(IBreadcrumbIgnorable)
    212 
    213 class CertificateCourseBreadcrumb(Breadcrumb):
    214     """ We don't want course container breadcrumbs.
    215     """
    216     grok.context(ICertificateCourse)
    217     @property
    218     def title(self):
    219         return self.context.longtitle
    220168
    221169def getBreadcrumb(obj, viewname=None):
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/browser.txt

    r11794 r11947  
    148148
    149149  >>> browser.open('http://localhost/myuniversity//@@change_language?lang=en')
    150 
    151 We can export a university as XML::
    152 
    153   >>> browser.open('http://localhost/myuniversity/export.xml')
    154   >>> print browser.contents
    155   <?xml version="1.0" encoding="utf-8" ?>
    156   <pickle>
    157   ...
    158   </pickle>
    159 
    160   >>> print browser.headers
    161   Status: 200 Ok
    162   Content-Length: ...
    163   Content-Type: text/xml; charset=UTF-8
    164   X-Powered-By: Zope (www.zope.org), Python (www.python.org)
    165150
    166151
     
    204189  >>> print root['myuniversity']['users']['bob'].roles
    205190  []
    206   >>> root['myuniversity']['users']['bob'].roles = ['waeup.ApplicationsOfficer']
     191  >>> root['myuniversity']['users']['bob'].roles = ['waeup.UsersManager']
    207192  >>> print root['myuniversity']['users']['bob'].roles
    208   ['waeup.ApplicationsOfficer']
     193  ['waeup.UsersManager']
    209194  >>> browser.open('http://localhost/myuniversity/users')
    210195  >>> print browser.contents
    211196  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    212   ...<td nowrap>Applications Officer (view only) <br /></td>
     197  ...<td nowrap>Users Manager <br /></td>
    213198  ...
    214199
     
    263248
    264249
    265 
    266 Faculties
    267 =========
    268 
    269 Faculties are stored in a special container of `IUniversity`
    270 instances. The container is called ``faculties`` and provides an
    271 add-form to add new faculties::
    272 
    273   >>> browser.open('http://localhost/myuniversity/faculties/manage')
    274   >>> browser.getControl('Add faculty').click()
    275   >>> print browser.contents
    276   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    277   ...*...
    278   ...<span>Name of faculty</span>:
    279   ...
    280   >>> browser.getControl('Cancel').click()
    281   >>> browser.open('http://localhost/myuniversity/faculties/add')
    282 
    283 We fill in a new name for our new faculty::
    284 
    285   >>> ctrl = browser.getControl(name='form.title')
    286   >>> ctrl.value = 'TestFac'
    287 
    288 Furthermore we add a prefix and a code (kind of abbreviation):
    289 
    290   >>> browser.getControl(name='form.code').value = 'TF'
    291 
    292 Finally we click on 'Add Faculty' to add the new thing::
    293 
    294   >>> browser.getControl('Add faculty').click()
    295 
    296 We can view a faculty by browsing a URL like this::
    297 
    298   >>> browser.open('http://localhost/myuniversity/faculties/TF')
    299 
    300 Afterwards, the faculty should be visible:
    301 
    302   >>> browser.open('http://localhost/myuniversity/faculties')
    303   >>> print browser.contents
    304   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    305   ...<h1 class="kofa-content-label">Academic Section</h1>
    306   ...<td> <a href="http://localhost/myuniversity/faculties/TF"> <span>TF</span></a></td>
    307   ...
    308 
    309 We can 'visit' each faculty by clicking on the appropriate link:
    310 
    311   >>> browser.getLink('TF').click()
    312   >>> print browser.contents
    313   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    314   ...Faculty of TestFac (TF)...
    315   ...
    316 
    317 If we add the same faculty twice, an error message will occur:
    318 
    319   >>> browser.open('http://localhost/myuniversity/faculties/add')
    320   >>> ctrl = browser.getControl(name='form.title')
    321   >>> ctrl.value = 'TestFac'
    322   >>> browser.getControl(name='form.code').value = 'TF'
    323   >>> browser.getControl('Add faculty').click()
    324   >>> 'The faculty code chosen already exists.' in browser.contents
    325   True
    326 
    327 Modifying faculties
    328 -------------------
    329 
    330 A faculty can directly be reached by its code:
    331 
    332   >>> browser.open('http://localhost/myuniversity/faculties/TF')
    333 
    334 We can change the settings for a faculty by clicking on the
    335 provided 'Manage  faculty' button:
    336 
    337   >>> browser.getLink('Manage faculty').click()
    338 
    339 Let's set a new title and save the form:
    340 
    341   >>> browser.getControl(name='form.title').value = "My renamed faculty"
    342   >>> browser.getControl(name='form.actions.save').click()
    343 
    344 Our faculty was indeed renamed to ``My renamed faculty``:
    345 
    346   >>> browser.open('http://localhost/myuniversity/faculties')
    347   >>> print browser.contents
    348   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    349   ...<h1 class="kofa-content-label">Academic Section</h1>
    350   ...<td> <a href="http://localhost/myuniversity/faculties/TF"> <span>TF</span></a></td>
    351   ...<td>Faculty of My renamed faculty (TF)</td>
    352   ...
    353 
    354 We can grant local roles:
    355 
    356   >>> root['myuniversity']['users'].addUser('bob', 'secret',title='Bob',
    357   ...                               description='A sample user')
    358   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    359   >>> browser.getControl(name="user").value = ['bob']
    360   >>> browser.getControl(
    361   ...     name="local_role").value = ['waeup.local.DepartmentManager']
    362   >>> browser.getControl("Add local role").click()
    363   >>> print browser.contents
    364   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    365   ...<td>bob</td>
    366   ...
    367 
    368 On the portal user page the new local role is displayed:
    369 
    370   >>> browser.getLink("Portal Users").click()
    371   >>> print browser.contents
    372   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    373   ...<td>Department Manager:...
    374   ...
    375 
    376 The local role can be removed again:
    377 
    378   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    379   >>> ctrl = browser.getControl(name='role_id')
    380   >>> browser.getControl("Remove selected local roles").click()
    381   >>> print browser.contents
    382   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    383   ...No local role selected...
    384   ...
    385 
    386   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    387   >>> ctrl = browser.getControl(name='role_id')
    388   >>> ctrl.getControl(value='bob|waeup.local.DepartmentManager').selected = True
    389   >>> browser.getControl("Remove selected local roles").click()
    390   >>> print browser.contents
    391   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    392   ...Local role successfully removed...
    393   ...
    394 
    395 Deleting faculties
    396 ------------------
    397 
    398   >>> browser.open('http://localhost/myuniversity/faculties/manage')
    399   >>> browser.getControl('Cancel').click()
    400   >>> print browser.url
    401   http://localhost/myuniversity/faculties
    402   >>> browser.getLink('Manage academic section').click()
    403   >>> browser.getControl('Add faculty').click()
    404   >>> ctrl = browser.getControl(name='form.title')
    405   >>> ctrl.value = 'Second Faculty'
    406   >>> browser.getControl(name='form.code').value = 'TF2'
    407   >>> browser.getControl('Add faculty').click()
    408   >>> browser.open('http://localhost/myuniversity/faculties/manage')
    409   >>> browser.getControl("Remove selected", index=0).click()
    410   >>> 'No item selected' in browser.contents
    411   True
    412   >>> browser.open('http://localhost/myuniversity/faculties/manage')
    413   >>> ctrl = browser.getControl(name='val_id')
    414   >>> ctrl.getControl(value='TF2').selected = True
    415   >>> browser.getControl("Remove selected", index=0).click()
    416   >>> print browser.contents
    417   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    418   ...Successfully removed:...
    419   ...
    420 
    421 Departments
    422 ===========
    423 
    424 Adding departments
    425 ------------------
    426 
    427 Departments are stored in :class:`IFaculty` instances with their code
    428 as key. Faculties therefore are also department containers. Faculties
    429 provides an add-form to add new departments:
    430 
    431   >>> browser.open('http://localhost/myuniversity/faculties/TF/add')
    432   >>> print browser.contents
    433   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    434   ...*</span>
    435   ...<span>Name of department</span>:
    436   ...
    437   >>> browser.getControl('Cancel').click()
    438   >>> browser.open('http://localhost/myuniversity/faculties/TF/add')
    439 
    440 We fill in a new name for our new department:
    441 
    442   >>> ctrl = browser.getControl(name='form.title')
    443   >>> ctrl.value = 'TestDept'
    444 
    445 Furthermore we add a code (kind of abbreviation):
    446 
    447   >>> browser.getControl(name='form.code').value = 'TD'
    448 
    449 Finally we click on 'Add Department' to add the new thing::
    450 
    451   >>> browser.getControl('Add department').click()
    452 
    453 If we try to register a department under the same code twice we will
    454 get an error:
    455 
    456   >>> browser.open('http://localhost/myuniversity/faculties/TF/add')
    457   >>> ctrl = browser.getControl(name='form.title')
    458   >>> ctrl.value = 'Another TestDept with same code'
    459   >>> browser.getControl(name='form.code').value = 'TD'
    460   >>> browser.getControl('Add department').click()
    461   >>> print browser.contents
    462   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    463   ...The code chosen already exists in this faculty...
    464   ...
    465 
    466 We can view a department by browsing a URL like this::
    467 
    468   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD')
    469 
    470 Afterwards, the department should be visible::
    471 
    472   >>> browser.open('http://localhost/myuniversity/faculties/TF')
    473   >>> print browser.contents
    474   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    475   ...<h1 class="kofa-content-label">Departments</h1>
    476   ...<td> <a href="http://localhost/myuniversity/faculties/TF/TD"> <span>TD</span></a></td>
    477   ...<td>Department of TestDept (TD)</td>
    478   ...
    479 
    480 
    481 Modifying departments
    482 ---------------------
    483 
    484 We can change the settings for a department by clicking on the
    485 provided 'Edit department' button:
    486 
    487   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD')
    488   >>> browser.getLink('Manage department').click()
    489 
    490 Let's set a new title and save the form:
    491 
    492   >>> browser.getControl(name='form.title').value = "My test dept"
    493   >>> browser.getControl(name='form.actions.save').click()
    494 
    495 Clicking 'Save' we will stay on the settings form. So we can change
    496 the department again.
    497 
    498   >>> browser.getControl(name='form.title').value = "My renamed dept"
    499   >>> ctrl = browser.getControl("Save")
    500   >>> ctrl.click()
    501 
    502 
    503 Our department was indeed renamed to ``My renamed dept``:
    504 
    505   >>> browser.open('http://localhost/myuniversity/faculties/TF')
    506   >>> print browser.contents
    507   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    508   ...<h1 class="kofa-content-label">Departments</h1>
    509   ...<td> <a href="http://localhost/myuniversity/faculties/TF/TD"> <span>TD</span></a></td>
    510   ...<td>Department of My renamed dept (TD)</td>
    511   ...
    512 
    513 We can grant local roles:
    514 
    515   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/manage')
    516   >>> browser.getControl(name="user").value = ['bob']
    517   >>> browser.getControl(
    518   ...     name="local_role").value = ['waeup.local.DepartmentManager']
    519   >>> browser.getControl("Add local role").click()
    520   >>> print browser.contents
    521   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    522   ...<td>bob</td>
    523   ...
    524 
    525 The local role can be removed again:
    526 
    527   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/manage')
    528   >>> ctrl = browser.getControl(name='role_id')
    529   >>> browser.getControl("Remove selected local roles").click()
    530   >>> print browser.contents
    531   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    532   ...No local role selected...
    533   ...
    534 
    535   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/manage')
    536   >>> ctrl = browser.getControl(name='role_id')
    537   >>> ctrl.getControl(
    538   ...     value='bob|waeup.local.DepartmentManager').selected = True
    539   >>> browser.getControl("Remove selected local roles").click()
    540   >>> print browser.contents
    541   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    542   ...Local role successfully removed...
    543   ...
    544 
    545 Deleting departments
    546 --------------------
    547 
    548   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    549   >>> browser.getControl('Cancel', index=0).click()
    550   >>> print browser.url
    551   http://localhost/myuniversity/faculties/TF
    552   >>> browser.getLink('Manage faculty').click()
    553   >>> browser.getControl('Add department').click()
    554   >>> ctrl = browser.getControl(name='form.title')
    555   >>> ctrl.value = 'Second Department'
    556   >>> browser.getControl(name='form.code').value = 'TD2'
    557   >>> browser.getControl('Add department').click()
    558   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    559   >>> browser.getControl("Remove selected", index=0).click()
    560   >>> 'No item selected' in browser.contents
    561   True
    562   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    563   >>> ctrl = browser.getControl(name='val_id')
    564   >>> ctrl.getControl(value='TD2').selected = True
    565   >>> browser.getControl("Remove selected", index=0).click()
    566   >>> print browser.contents
    567   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    568   ...Successfully removed:...
    569   ...
    570 
    571 
    572 Courses
    573 =======
    574 
    575 Once we have a department, we can add courses.
    576 
    577 Adding courses
    578 --------------
    579 
    580 Courses are stored in :class:`ICoursesContainer` instances with their
    581 code as key. CoursesContainers are normally availabe as `course`
    582 attribute of :class:`waeup.kofa.university.department.Department`
    583 instances.
    584 
    585 To ease the life of users we do not require to browse the
    586 coursescontainers (which have a rather flat user interface), but
    587 provide adding of courses in department views.
    588 
    589 Each department provides a ``Add course`` action button near top.
    590 
    591 Departments provide an add-form to add new courses:
    592 
    593   >>> dept_url = 'http://localhost/myuniversity/faculties/TF/TD'
    594   >>> browser.open(dept_url + '/manage')
    595   >>> browser.getControl('Add course').click()
    596   >>> print browser.contents
    597   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    598   ...*</span>
    599   ...<span>Title of course</span>:
    600   ...
    601 
    602 We fill in a name for our new course:
    603 
    604   >>> ctrl = browser.getControl(name='form.title')
    605   >>> ctrl.value = 'My Course 1'
    606 
    607 Furthermore we add a code (kind of abbreviation):
    608 
    609   >>> browser.getControl(name='form.code').value = 'COURSE1'
    610 
    611 This course will take place in the the first semester, so we set the
    612 `semester` value to 1:
    613 
    614   >>> ctrl = browser.getControl(name='form.semester')
    615   >>> ctrl.options
    616   ['1', '2', '3', '9']
    617 
    618   >>> ctrl.displayOptions
    619   ['1st Semester', '2nd Semester', 'Combined', 'N/A']
    620 
    621   >>> ctrl.value = ['1']
    622 
    623 Finally, we create the course:
    624 
    625   >>> browser.getControl('Add course').click()
    626 
    627 If we try to register a course under the same code twice we will
    628 get an error:
    629 
    630   >>> browser.open(dept_url + '/addcourse')
    631   >>> ctrl = browser.getControl(name='form.title')
    632   >>> ctrl.value = 'Another course with same code'
    633   >>> browser.getControl(name='form.code').value = 'COURSE1'
    634   >>> browser.getControl('Add course').click()
    635   >>> print browser.contents
    636   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    637   ...A course with same code already exists:...
    638   ...
    639 
    640 Our course will be linked under the code on the department page:
    641 
    642   >>> browser.open(dept_url)
    643   >>> browser.getLink('COURSE1').click()
    644   >>> browser.url
    645   'http://localhost/myuniversity/faculties/TF/TD/courses/COURSE1'
    646 
    647 Before we really add a course we can cancel the action and will be
    648 redirected to the department page:
    649 
    650   >>> browser.open(dept_url + '/addcourse')
    651   >>> browser.getControl('Cancel').click()
    652   >>> browser.url
    653   'http://localhost/myuniversity/faculties/TF/TD'
    654 
    655 
    656 Modifying courses
    657 -----------------
    658 
    659 We can change the settings for a course by clicking on the provided
    660 'Edit settings' link:
    661 
    662   >>> browser.open(dept_url + '/courses/COURSE1')
    663   >>> browser.getLink('Edit course').click()
    664 
    665 When modifying a course, we cannot change the code any more:
    666 
    667   >>> browser.getControl(name='form.code')
    668   Traceback (most recent call last):
    669   ...
    670   LookupError: name 'form.code'
    671 
    672 Let's set a new title and save the form:
    673 
    674   >>> browser.getControl(name='form.title').value = "My test course"
    675   >>> browser.getControl(name='form.actions.save').click()
    676 
    677 Clicking 'Save' we will stay on the settings form. So we can change
    678 the course again. If we click ``Cancel`` nothing will be
    679 changed:
    680 
    681   >>> browser.getControl(name='form.title').value = "Blah"
    682   >>> browser.getControl('Cancel').click()
    683 
    684 Our course was not renamed to ``Blah``:
    685 
    686   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD')
    687   >>> print browser.contents
    688   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    689   ...<td>My test course</td>...
    690   ...
    691 
    692 Searching courses
    693 -----------------
    694 
    695   >>> browser.open('http://localhost/myuniversity/faculties/search')
    696   >>> browser.getControl(name='query').value = "My test course"
    697   >>> browser.getControl('Search').click()
    698   >>> print browser.contents
    699   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    700   ...faculties/TF/TD/courses/COURSE1">COURSE1</a>
    701   ...
    702 
    703   >>> browser.open('http://localhost/myuniversity/faculties/search')
    704   >>> browser.getControl(name='query').value = "COURSE1"
    705   >>> browser.getControl('Search').click()
    706   >>> print browser.contents
    707   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    708   ...faculties/TF/TD/courses/COURSE1">COURSE1</a>
    709   ...
    710 
    711   >>> browser.getControl(name='query').value = "Nonsense"
    712   >>> browser.getControl('Search').click()
    713   >>> 'Search Results' in browser.contents
    714   False
    715   >>> '<div class="alert alert-warning">No object found.</div>' in browser.contents
    716   True
    717 
    718   >>> browser.getControl(name='query').value = ""
    719   >>> browser.getControl('Search').click()
    720   >>> 'Empty search string' in browser.contents
    721   True
    722 
    723 We can grant local roles:
    724 
    725   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/courses/COURSE1/manage')
    726   >>> browser.getControl(name="user").value = ['bob']
    727   >>> browser.getControl(
    728   ...     name="local_role").value = ['waeup.local.Lecturer']
    729   >>> browser.getControl("Add local role").click()
    730   >>> print browser.contents
    731   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    732   ...<td>bob</td>
    733   ...
    734 
    735 On the portal user page the new local role is displayed:
    736 
    737   >>> browser.getLink("Portal Users").click()
    738   >>> print browser.contents
    739   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    740   ...<td>Lecturer:...
    741   ...
    742 
    743 The local role can be removed again:
    744 
    745   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/courses/COURSE1/manage')
    746   >>> ctrl = browser.getControl(name='role_id')
    747   >>> browser.getControl("Remove selected local roles").click()
    748   >>> print browser.contents
    749   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    750   ...No local role selected...
    751   ...
    752 
    753   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD/courses/COURSE1/manage')
    754   >>> ctrl = browser.getControl(name='role_id')
    755   >>> ctrl.getControl(value='bob|waeup.local.Lecturer').selected = True
    756   >>> browser.getControl("Remove selected local roles").click()
    757   >>> print browser.contents
    758   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    759   ...Local role successfully removed...
    760   ...
    761 
    762 Deleting courses
    763 ----------------
    764 
    765 We can delete courses by browsing the manage page of the containing
    766 department and checking the appropriate select box and clicking the
    767 ´´Remove selected´´ button.
    768 
    769   >>> browser.open(
    770   ...     'http://localhost/myuniversity/faculties/TF/TD/@@manage#tab-2')
    771   >>> 'My test course' in browser.contents
    772   True
    773 
    774   >>> browser.getControl('Cancel', index=0).click()
    775   >>> browser.getLink('Manage department').click()
    776   >>> browser.getControl('Remove selected courses').click()
    777   >>> 'No item selected' in browser.contents
    778   True
    779 
    780   >>> browser.getControl(
    781   ...    name='val_id').getControl(value='COURSE1').selected = True
    782   >>> browser.getControl('Remove selected courses').click()
    783 
    784   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD')
    785   >>> 'My renamed course' in browser.contents
    786   False
    787 
    788 
    789 Deleting departments with courses
    790 ---------------------------------
    791 
    792   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    793   >>> browser.getControl('Cancel', index=0).click()
    794   >>> browser.getLink('Manage faculty').click()
    795   >>> browser.getControl('Add department').click()
    796   >>> ctrl = browser.getControl(name='form.title')
    797   >>> ctrl.value = 'Third Department'
    798   >>> browser.getControl(name='form.code').value = 'TD3'
    799   >>> browser.getControl('Add department').click()
    800   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD3/manage')
    801   >>> browser.getControl('Add course').click()
    802   >>> ctrl = browser.getControl(name='form.title')
    803   >>> ctrl.value = 'My Course 5'
    804   >>> browser.getControl(name='form.code').value = 'COURSE5'
    805   >>> browser.getControl('Add course').click()
    806   >>> browser.open('http://localhost/myuniversity/faculties/TF/manage')
    807   >>> ctrl = browser.getControl(name='val_id')
    808   >>> ctrl.getControl(value='TD3').selected = True
    809   >>> browser.getControl("Remove selected", index=0).click()
    810   >>> print browser.contents
    811   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    812   ...Successfully removed:...
    813   ...
    814 
    815 Certificates
    816 ============
    817 
    818 Once we have a department, we can add also certificats.
    819 
    820 Adding certificates
    821 -------------------
    822 
    823 Certificates are stored in :class:`ICertificatesContainer` instances
    824 with their code as key. CertificatesContainers are normally availabe as
    825 `certificates` attribute of
    826 :class:`waeup.kofa.university.department.Department` instances.
    827 
    828 To ease the life of users we do not require to browse the
    829 certificatescontainers (which have in fact no user interface), but
    830 provide adding of certificates in department views.
    831 
    832 Each department provides a ``Add certificate`` action button near top.
    833 
    834 Departments provide an add-form to add new certificates:
    835 
    836   >>> dept_url = 'http://localhost/myuniversity/faculties/TF/TD'
    837   >>> browser.open(dept_url + '/manage')
    838   >>> browser.getControl('Add certificate').click()
    839   >>> print browser.contents
    840   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    841   ...*</span>
    842   ...<span>Title</span>:
    843   ...
    844 
    845 We fill in a name for our new cert:
    846 
    847   >>> ctrl = browser.getControl(name='form.title')
    848   >>> ctrl.value = 'My Certificate 1'
    849 
    850 Furthermore we add a code (kind of abbreviation):
    851 
    852   >>> browser.getControl(name='form.code').value = 'CERT1'
    853 
    854 Set the remaining required fields:
    855 
    856   >>> browser.getControl(name='form.study_mode').value = ['ug_ft']
    857   >>> browser.getControl(name='form.start_level').value = ['100']
    858   >>> browser.getControl(name='form.end_level').value = ['400']
    859   >>> browser.getControl(name='form.application_category').value = ['basic']
    860 
    861 Finally, we create the certificate:
    862 
    863   >>> browser.getControl('Add certificate').click()
    864 
    865 If we try to register a certificate under the same code twice we will
    866 get an error:
    867 
    868   >>> browser.open(dept_url + '/addcertificate')
    869   >>> ctrl = browser.getControl(name='form.title')
    870   >>> ctrl.value = 'Another cert with same code'
    871   >>> browser.getControl(name='form.code').value = 'CERT1'
    872   >>> browser.getControl(name='form.study_mode').value = ['ug_ft']
    873   >>> browser.getControl(name='form.start_level').value = ['100']
    874   >>> browser.getControl(name='form.end_level').value = ['400']
    875   >>> browser.getControl(name='form.application_category').value = ['basic']
    876 
    877   >>> browser.getControl('Add certificate').click()
    878   >>> print browser.contents
    879   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    880   ...A certificate with same code already exists:...
    881   ...
    882 
    883 Our certificate will be linked under the code on the department page:
    884 
    885   >>> browser.open(dept_url)
    886   >>> browser.getLink('CERT1').click()
    887   >>> browser.url
    888   'http://localhost/myuniversity/faculties/TF/TD/certificates/CERT1'
    889 
    890 Before we really add a certificate we can cancel the action and will be
    891 redirected to the department page:
    892 
    893   >>> browser.open(dept_url + '/addcertificate')
    894   >>> browser.getControl('Cancel').click()
    895   >>> browser.url
    896   'http://localhost/myuniversity/faculties/TF/TD'
    897 
    898 
    899 Modifying certificates
    900 ----------------------
    901 
    902 We can change the settings for a cert by clicking on the provided
    903 'Edit certificate' link:
    904 
    905   >>> browser.open(dept_url + '/certificates/CERT1')
    906   >>> browser.getLink('Manage certificate').click()
    907 
    908 When modifying a certificate, we cannot change the code any more:
    909 
    910   >>> browser.getControl(name='form.code')
    911   Traceback (most recent call last):
    912   ...
    913   LookupError: name 'form.code'
    914 
    915 Let's set a new title and save the form:
    916 
    917   >>> browser.getControl(name='form.title').value = "My test cert"
    918   >>> browser.getControl(name='form.actions.save').click()
    919 
    920 Clicking 'Save' we will stay on the settings form. So we can change
    921 the cert again.
    922 
    923   >>> browser.getControl(name='form.title').value = "My renamed cert"
    924   >>> ctrl = browser.getControl("Save",index=0)
    925   >>> ctrl.click()
    926 
    927 If we go to the settings page and click ``Cancel`` nothing will be
    928 changed:
    929 
    930   >>> browser.getControl(name='form.title').value = "Blah"
    931   >>> browser.getControl('Cancel',index=0).click()
    932 
    933 Our certificate was indeed renamed to ``My renamed cert`` and not to
    934 ``Blah``:
    935 
    936   >>> browser.open('http://localhost/myuniversity/faculties/TF/TD')
    937   >>> print browser.contents
    938   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    939   ...<td>My renamed cert</td>...
    940   ...
    941 
    942 Searching certificates
    943 ----------------------
    944 
    945   >>> browser.open('http://localhost/myuniversity/faculties/search')
    946   >>> browser.getControl(name='query').value = "My renamed cert"
    947   >>> browser.getControl('Search').click()
    948   >>> print browser.contents
    949   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    950   ...faculties/TF/TD/certificates/CERT1">CERT1</a>
    951   ...
    952 
    953   >>> browser.open('http://localhost/myuniversity/faculties/search')
    954   >>> browser.getControl(name='query').value = "CERT1"
    955   >>> browser.getControl('Search').click()
    956   >>> print browser.contents
    957   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    958   ...faculties/TF/TD/certificates/CERT1">CERT1</a>
    959   ...
    960 
    961 Deleting certificates
    962 ---------------------
    963 
    964 We can delete certificates by browsing the manage page of the
    965 containing department and checking the appropriate select box and
    966 clicking the ´´Remove selected´´ button.
    967 
    968   >>> browser.open(
    969   ...    'http://localhost/myuniversity/faculties/TF/TD/@@manage#tab-3')
    970   >>> 'My renamed cert' in browser.contents
    971   True
    972 
    973   >>> browser.getControl('Remove selected certificates').click()
    974   >>> 'No item selected' in browser.contents
    975   True
    976 
    977   >>> browser.getControl(name='val_id').getControl(
    978   ...    value='CERT1').selected = True
    979   >>> browser.getControl('Remove selected certificates').click()
    980   >>> 'My renamed cert' in browser.contents
    981   False
    982 
    983 
    984 CertificateCourses
    985 ==================
    986 
    987 Once we have a certificate, we can add also certificate courses. These
    988 are referrers of courses with some extra data.
    989 
    990 Before we can work with certificate courses, we need some certificates
    991 and courses to be available.
    992 
    993   >>> browser.open(dept_url + '/addcourse')
    994   >>> ctrl = browser.getControl(name='form.title')
    995   >>> ctrl.value = 'Another course with same code'
    996   >>> browser.getControl(name='form.code').value = 'COURSE1'
    997   >>> browser.getControl(name='form.title').value = 'Course 1'
    998   >>> browser.getControl('Add course').click()
    999 
    1000   >>> browser.open(dept_url + '/addcourse')
    1001   >>> ctrl = browser.getControl(name='form.title')
    1002   >>> ctrl.value = 'Another course with same code'
    1003   >>> browser.getControl(name='form.code').value = 'COURSE2'
    1004   >>> browser.getControl(name='form.title').value = 'Course 2'
    1005   >>> browser.getControl('Add course').click()
    1006 
    1007   >>> browser.open(dept_url + '/addcertificate')
    1008   >>> ctrl = browser.getControl(name='form.title')
    1009   >>> ctrl.value = 'Another cert with same code'
    1010   >>> browser.getControl(name='form.code').value = 'CERT1'
    1011   >>> browser.getControl(name='form.title').value = 'Certificate 1'
    1012   >>> browser.getControl(name='form.study_mode').value = ['ug_ft']
    1013   >>> browser.getControl(name='form.start_level').value = ['100']
    1014   >>> browser.getControl(name='form.end_level').value = ['400']
    1015   >>> browser.getControl(name='form.application_category').value = ['basic']
    1016   >>> browser.getControl('Add certificate').click()
    1017 
    1018   >>> browser.open(dept_url + '/addcertificate')
    1019   >>> ctrl = browser.getControl(name='form.title')
    1020   >>> ctrl.value = 'Another cert with same code'
    1021   >>> browser.getControl(name='form.code').value = 'CERT2'
    1022   >>> browser.getControl(name='form.title').value = 'Certificate 2'
    1023   >>> browser.getControl(name='form.study_mode').value = ['ug_ft']
    1024   >>> browser.getControl(name='form.start_level').value = ['100']
    1025   >>> browser.getControl(name='form.end_level').value = ['400']
    1026   >>> browser.getControl(name='form.application_category').value = ['basic']
    1027   >>> browser.getControl('Add certificate').click()
    1028 
    1029 
    1030 Adding certificatecourses
    1031 -------------------------
    1032 
    1033 Certcourses are stored in :class:`ICertificate` instances
    1034 with their code as key.
    1035 
    1036 Each certificate provides a ``Add certificate course`` action button near top.
    1037 
    1038 Certificates provide an add-form to add new certcourses:
    1039 
    1040   >>> cert_url = dept_url + '/certificates/CERT1'
    1041   >>> browser.open(cert_url + '/manage')
    1042   >>> browser.getControl('Add certificate course').click()
    1043   >>> print browser.contents
    1044   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    1045   ...*</span>
    1046   ...<span>Level</span>:
    1047   ...
    1048 
    1049 In the add-form we will get a list of available courses to select
    1050 from. This list will contain all courses stored in the site, not only
    1051 the ones from local department:
    1052 
    1053   >>> ctrl = browser.getControl(name='form.course')
    1054   >>> ctrl.displayOptions
    1055   ['--', 'COURSE1 - Course 1', 'COURSE2 - Course 2']
    1056 
    1057 We select the first course and create our certificatecourse:
    1058 
    1059   >>> ctrl.getControl('COURSE1').selected = True
    1060   >>> browser.getControl(name='form.level').value = ['100']
    1061   >>> browser.getControl('Add certificate course').click()
    1062 
    1063 Our certificatecourse will be linked on the parent certificate page:
    1064 
    1065   >>> browser.open(cert_url)
    1066   >>> browser.getLink('COURSE1_100').click()
    1067   >>> browser.url
    1068   'http://localhost/my...sity/faculties/TF/TD/certificates/CERT1/COURSE1_100'
    1069 
    1070 We can't add the same certificatecourse twice:
    1071 
    1072   >>> cert_url = dept_url + '/certificates/CERT1'
    1073   >>> browser.open(cert_url + '/manage')
    1074   >>> browser.getControl('Add certificate course').click()
    1075   >>> ctrl = browser.getControl(name='form.course')
    1076   >>> ctrl.getControl('COURSE1').selected = True
    1077   >>> browser.getControl(name='form.level').value = ['100']
    1078   >>> browser.getControl('Add certificate course').click()
    1079   >>> 'The chosen certificate course is already' in browser.contents
    1080   True
    1081 
    1082 When we started to add a new certificatecourse, we can also cancel the
    1083 process before submitting. This will bring us back to the certificate
    1084 page:
    1085 
    1086   >>> browser.open(cert_url + '/addcertificatecourse')
    1087   >>> browser.getControl('Cancel').click()
    1088   >>> browser.url
    1089   'http://localhost/myuniversity/faculties/TF/TD/certificates/CERT1'
    1090 
    1091 
    1092 Modifying certificatecourses
    1093 ----------------------------
    1094 
    1095 We can change the settings for a certcourse by clicking on the
    1096 provided 'Edit certificate course' link:
    1097 
    1098   >>> browser.open(cert_url + '/COURSE1_100')
    1099   >>> browser.getLink('Edit certificate course').click()
    1100 
    1101 If we just click 'Save and return' nothing will change:
    1102 
    1103   >>> browser.getControl("Save and return").click()
    1104   >>> browser.getLink('COURSE1_100').click()
    1105   >>> browser.url
    1106   'http://localhost/myun.../TF/TD/certificates/CERT1/COURSE1_100'
    1107 
    1108 Let's set a new level (it was 100 before) and save the form. This will
    1109 bring us to the certificate index page afterwards:
    1110 
    1111   >>> browser.open(cert_url + '/COURSE1_100/manage')
    1112   >>> browser.getControl(name='form.level').value = ['200']
    1113   >>> browser.getControl("Save and return").click()
    1114 
    1115 As we changed the level, also the URL will change:
    1116 
    1117   >>> browser.getLink('COURSE1_200').click()
    1118   >>> browser.url
    1119   'http://localhost/myun.../TF/TD/certificates/CERT1/COURSE1_200'
    1120 
    1121 If we go to the settings page and click ``Cancel`` nothing will be
    1122 changed:
    1123 
    1124   >>> browser.getLink('Edit certificate course').click()
    1125   >>> browser.getControl(name='form.level').value = ['400']
    1126   >>> browser.getControl('Cancel').click()
    1127 
    1128 Our certcourse provides a new level of 200 and not 400:
    1129 
    1130   >>> browser.open(cert_url + '/COURSE1_200')
    1131   >>> print browser.contents
    1132   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    1133   ...<td>Level:</td>
    1134   ...<td>200 (Year 2)</td>
    1135   ...
    1136 
    1137 Searching certificatecourses
    1138 ----------------------------
    1139 
    1140   >>> browser.open('http://localhost/myuniversity/faculties/search')
    1141   >>> browser.getControl(name='query').value = "COURSE1"
    1142   >>> browser.getControl('Search').click()
    1143   >>> print browser.contents
    1144   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
    1145   ...faculties/TF/TD/certificates/CERT1/COURSE1_200">COURSE1</a>
    1146   ...
    1147 
    1148   >>> browser.getControl(name='query').value = "*"
    1149   >>> browser.getControl('Search').click()
    1150   >>> 'Search string not allowed' in browser.contents
    1151   True
    1152 
    1153 Deleting certificatecourses
    1154 ---------------------------
    1155 
    1156 We can delete certcourses by browsing the containing certificate manage page:
    1157 
    1158   >>> browser.open(cert_url + '/manage#tab-2')
    1159   >>> 'COURSE1_200</a>' in browser.contents
    1160   True
    1161   >>> browser.getControl('Remove selected certificate courses').click()
    1162   >>> 'No item selected' in browser.contents
    1163   True
    1164   >>> browser.getControl(name='val_id').getControl(
    1165   ...    value='COURSE1_200').selected = True
    1166   >>> browser.getControl('Remove selected certificate courses').click()
    1167   >>> 'Successfully removed: COURSE1_200' in browser.contents
    1168   True
    1169 
    1170   >>> 'COURSE1_200</a>' in browser.contents
    1171   False
    1172 
    1173 
    1174 
    1175250Data Center
    1176251===========
     
    1276351  ['deleted', 'finished', 'logs', 'myfaculties_zope.mgr.csv', 'unfinished']
    1277352
    1278 We create and upload also a CSV file containing departments:
    1279 
    1280   >>> open('departments.csv', 'wb').write(
    1281   ... """code,title,title_prefix,faculty_code
    1282   ... LIT,Literature,department,FA
    1283   ... SOC,Sociology,department,FA
    1284   ... PHY,Physics,department,FS
    1285   ... INF,Informatics,department,FS
    1286   ... MAT,Math,department,FS
    1287   ... """)
    1288 
    1289   >>> browser.open('http://localhost/myuniversity/datacenter/upload')
    1290   >>> browser.getControl(name='uploadfile:file').add_file(
    1291   ...   cStringIO.StringIO(open('departments.csv', 'rb').read()),
    1292   ...   'text/plain', 'mydepartments.csv')
    1293   >>> browser.getControl(name='SUBMIT').click()
    1294 
    1295 We create and upload also a CSV file containing courses:
    1296 
    1297   >>> open('courses.csv', 'wb').write(
    1298   ... """code,level,title,passmark,credits,semester,faculty,department
    1299   ... LI1,,Introduction to Literature I,40,2,1,FA,LIT
    1300   ... LI2,,Introduction to Literature II,40,2,2,FA,LIT
    1301   ... AN1,000,Analysis I,40,2,1,FS,MAT
    1302   ... AN2,000,Analysis II,40,2,2,FS,MAT
    1303   ... """)
    1304 
    1305   >>> browser.open('http://localhost/myuniversity/datacenter/upload')
    1306   >>> browser.getControl(name='uploadfile:file').add_file(
    1307   ...   cStringIO.StringIO(open('courses.csv', 'rb').read()),
    1308   ...   'text/plain', 'mycourses.csv')
    1309   >>> browser.getControl(name='SUBMIT').click()
    1310 
    1311 We create and upload also a CSV file containing certificates:
    1312 
    1313   >>> open('certificates.csv', 'wb').write(
    1314   ... """code,title,faculty_code,department_code,study_mode,end_level,m_prefix,start_level,application_category
    1315   ... LBA,BACHELOR OF LITERATURE,FA,LIT,UG,ug_ft,500,LIT,100,basic
    1316   ... LMA,MASTER OF LITERATURE,FA,LIT,UG,ug_pt,500,LIT,100,cest
    1317   ... DME,DIPLOMA OF MATH,FS,MAT,DP,dp_ft,200,DME,100,cest
    1318   ... """)
    1319 
    1320   >>> browser.open('http://localhost/myuniversity/datacenter/upload')
    1321   >>> browser.getControl(name='uploadfile:file').add_file(
    1322   ...   cStringIO.StringIO(open('certificates.csv', 'rb').read()),
    1323   ...   'text/plain', 'mycertificates.csv')
    1324   >>> browser.getControl(name='SUBMIT').click()
    1325 
    1326 We create and upload also a CSV file containing certificate courses:
    1327 
    1328   >>> open('certcourses.csv', 'wb').write(
    1329   ... """code,faculty_code,department_code,certificate_code,level,mandatory
    1330   ... LI1,FA,LIT,LBA,100,True
    1331   ... LI2,FA,LIT,LBA,200,True
    1332   ... """)
    1333 
    1334   >>> browser.open('http://localhost/myuniversity/datacenter/upload')
    1335   >>> browser.getControl(name='uploadfile:file').add_file(
    1336   ...   cStringIO.StringIO(open('certcourses.csv', 'rb').read()),
    1337   ...   'text/plain', 'mycertcourses.csv')
    1338   >>> browser.getControl(name='SUBMIT').click()
    1339353
    1340354
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/interfaces.py

    r11254 r11947  
    2323    IKofaObject, IUniversity, IUsersContainer, IDataCenter, validate_email)
    2424from waeup.kofa.interfaces import MessageFactory as _
    25 from waeup.kofa.university.interfaces import (
    26     IFacultiesContainer, IFaculty, IDepartment,
    27     ICoursesContainer, ICourse, ICertificatesContainer,
    28     ICertificate, ICertificateCourse)
    2925
    3026class IBreadcrumb(Interface):
     
    177173        title = _(u'Unique Identifier'),
    178174        description = _(
    179             u'User Name, Student or Applicant Id, Matriculation or '
     175            u'User Name, Customer Id, or '
    180176            u'Registration Number'),
    181177        required = True,
     
    188184        constraint=validate_email,
    189185        )
    190 
    191 class IStudentNavigationBase(IKofaObject):
    192     """Objects that provide student navigation (whatever it is) should
    193        implement this interface.
    194     """
    195     student = Attribute('''Some student object that has a '''
    196                         ''' `display_fullname` attribute.''')
    197 
    198 class IApplicantBase(IKofaObject):
    199     """Some Applicant.
    200     """
    201     display_fullname = Attribute('''Fullname.''')
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/layout.py

    r11437 r11947  
    3535from waeup.kofa.interfaces import MessageFactory as _
    3636from waeup.kofa.utils.helpers import to_timezone
    37 from waeup.kofa.browser.interfaces import (
    38     IStudentNavigationBase, IApplicantBase)
    3937from waeup.kofa.authentication import get_principal_role_manager
    4038
     
    254252        return userid
    255253
    256     def isStudent(self):
     254    def isCustomer(self):
    257255        usertype = getattr(self.request.principal, 'user_type', None)
    258256        if not usertype:
    259257            return False
    260         return self.request.principal.user_type == 'student'
    261 
    262     def isApplicant(self):
    263         usertype = getattr(self.request.principal, 'user_type', None)
    264         if not usertype:
    265             return False
    266         return self.request.principal.user_type == 'applicant'
    267 
    268     def getStudentName(self):
    269         """Return the student name.
    270         """
    271         if IStudentNavigationBase.providedBy(self.context):
    272             return self.context.student.display_fullname
    273         return
     258        return self.request.principal.user_type == 'customer'
    274259
    275260    def formatDatetime(self,datetimeobj):
     
    301286
    302287    def render(self):
    303         if self.isStudent() or self.isApplicant() or not self.isAuthenticated():
     288        if self.isCustomer() or not self.isAuthenticated():
    304289            return self.studenttemp.render(self)
    305290        return self.stafftemp.render(self)
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/pages.py

    r11889 r11947  
    4646    KofaDisplayFormPage, NullValidator)
    4747from waeup.kofa.browser.interfaces import (
    48     IUniversity, IFacultiesContainer, IFaculty,
    49     IDepartment, ICourse, ICertificate,
    50     ICertificateCourse,
    51     ICaptchaManager, IChangePassword)
     48    IUniversity, ICaptchaManager, IChangePassword)
    5249from waeup.kofa.browser.layout import jsaction, action, UtilityView
    5350from waeup.kofa.interfaces import MessageFactory as _
     
    5855    ISessionConfiguration, ISessionConfigurationAdd, IJobManager,
    5956    IPasswordValidator, IContactForm, IKofaUtils, ICSVExporter,
    60     academic_sessions_vocab)
     57    application_sessions_vocab)
    6158from waeup.kofa.permissions import (
    6259    get_users_with_local_roles, get_all_roles, get_all_users,
    6360    get_users_with_role)
    6461
    65 from waeup.kofa.university.catalog import search
    66 from waeup.kofa.university.vocabularies import course_levels
    6762from waeup.kofa.authentication import LocalRoleSetEvent
    6863from waeup.kofa.widgets.htmlwidget import HTMLDisplayWidget
     
    7065from waeup.kofa.mandates.mandate import PasswordMandate
    7166from waeup.kofa.datacenter import DataCenterFile
    72 
    73 from waeup.kofa.students.export import EXPORTER_NAMES as STUDENT_EXPORTERS
    74 from waeup.kofa.students.catalog import StudentQueryResultItem
    7567
    7668FORBIDDEN_CHARACTERS = (160,)
     
    270262    login_button = label
    271263
    272     def _comment(self, student):
    273         return getattr(student, 'suspended_comment', None)
    274 
    275264    def update(self, SUBMIT=None, camefrom=None):
    276265        self.camefrom = camefrom
     
    278267            if self.request.principal.id != 'zope.anybody':
    279268                self.flash(_('You logged in.'))
    280                 if self.request.principal.user_type == 'student':
    281                     student = grok.getSite()['students'][
     269                if self.request.principal.user_type == 'customer':
     270                    student = grok.getSite()['customerss'][
    282271                        self.request.principal.id]
    283                     rel_link = '/students/%s' % self.request.principal.id
     272                    rel_link = '/customers/%s' % self.request.principal.id
    284273                    if student.personal_data_expired:
    285                         rel_link = '/students/%s/edit_personal' % (
     274                        rel_link = '/customerss/%s/edit_personal' % (
    286275                            self.request.principal.id)
    287276                        self.flash(
    288277                          _('Your personal data record is outdated. Please update.'),
    289278                          type='warning')
    290                     self.redirect(self.application_url() + rel_link)
    291                     return
    292                 elif self.request.principal.user_type == 'applicant':
    293                     container, application_number = self.request.principal.id.split('_')
    294                     rel_link = '/applicants/%s/%s' % (
    295                         container, application_number)
    296279                    self.redirect(self.application_url() + rel_link)
    297280                    return
     
    301284                self.redirect(self.camefrom)
    302285                return
    303             # Display appropriate flash message if credentials are correct
    304             # but student has been deactivated or a temporary password
    305             # has been set.
    306             login = self.request.form['form.login']
    307             if len(login) == 8 and login in grok.getSite()['students']:
    308                 student = grok.getSite()['students'][login]
    309                 password = self.request.form['form.password']
    310                 passwordmanager = getUtility(IPasswordManager, 'SSHA')
    311                 if student.password is not None and \
    312                     passwordmanager.checkPassword(student.password, password):
    313                     # The student entered valid credentials.
    314                     # First we check if a temporary password has been set.
    315                     delta = timedelta(minutes=10)
    316                     now = datetime.utcnow()
    317                     temp_password_dict = getattr(student, 'temp_password', None)
    318                     if temp_password_dict is not None and \
    319                         now < temp_password_dict.get('timestamp', now) + delta:
    320                         self.flash(
    321                             _('Your account has been temporarily deactivated.'),
    322                             type='warning')
    323                         return
    324                     # Now we know that the student is suspended.
    325                     comment = self._comment(student)
    326                     if comment:
    327                         self.flash(comment, type='warning')
    328                     else:
    329                         self.flash(_('Your account has been deactivated.'),
    330                                    type='warning')
    331                     return
    332286            self.flash(_('You entered invalid credentials.'), type='danger')
    333287            return
     
    734688
    735689#
    736 # Search pages...
    737 #
    738 
    739 class SearchPage(KofaPage):
    740     """General search page for the academics section.
    741     """
    742     grok.context(IFacultiesContainer)
    743     grok.name('search')
    744     grok.template('searchpage')
    745     grok.require('waeup.viewAcademics')
    746     label = _(u"Search Academic Section")
    747     pnav = 1
    748     search_button = _(u'Search')
    749 
    750     def update(self, *args, **kw):
    751         form = self.request.form
    752         self.hitlist = []
    753         self.query = ''
    754         if not 'query' in form:
    755             return
    756         query = form['query']
    757         self.query = query
    758         self.hitlist = search(query=self.query, view=self)
    759         if not self.hitlist:
    760             self.flash(_('No object found.'), type="warning")
    761         return
    762 
    763 #
    764690# Configuration pages...
    765691#
     
    856782            self.context.__parent__.logger.info(
    857783                '%s - added: %s' % (
    858                 ob_class, sessionconfiguration.academic_session))
     784                ob_class, sessionconfiguration.application_session))
    859785        except KeyError:
    860786            self.flash(_('The session chosen already exists.'), type='danger')
     
    15181444        self.filename = logname
    15191445        self.query = query
    1520         if search is None or not query:
     1446        if not query:
    15211447            return
    15221448        try:
     
    15821508        utils = getUtilitiesFor(ICSVExporter)
    15831509        title_name_tuples = [
    1584             (util.title, name) for name, util in utils
    1585             if not name in STUDENT_EXPORTERS]
    1586         # The exporter for access codes requires a special permission.
    1587         if not checkPermission('waeup.manageACBatches', self.context):
    1588             title_name_tuples.remove((u'AccessCodes', u'accesscodes'))
     1510            (util.title, name) for name, util in utils]
    15891511        return sorted(title_name_tuples)
    15901512
     
    16431565        return result
    16441566
    1645 class ExportXMLPage(grok.View):
    1646     """Deliver an XML representation of the context.
    1647     """
    1648     grok.name('export.xml')
    1649     grok.require('waeup.managePortal')
    1650 
    1651     def render(self):
    1652         exporter = IKofaXMLExporter(self.context)
    1653         xml = exporter.export().read()
    1654         self.response.setHeader(
    1655             'Content-Type', 'text/xml; charset=UTF-8')
    1656         return xml
    1657 
    1658 class ImportXMLPage(KofaPage):
    1659     """Replace the context object by an object created from an XML
    1660        representation.
    1661 
    1662        XXX: This does not work for ISite objects, i.e. for instance
    1663             for complete University objects.
    1664     """
    1665     grok.name('importxml')
    1666     grok.require('waeup.managePortal')
    1667 
    1668     def update(self, xmlfile=None, CANCEL=None, SUBMIT=None):
    1669         if CANCEL is not None:
    1670             self.redirect(self.url(self.context))
    1671             return
    1672         if not xmlfile:
    1673             return
    1674         importer = IKofaXMLImporter(self.context)
    1675         obj = importer.doImport(xmlfile)
    1676         if type(obj) != type(self.context):
    1677             return
    1678         parent = self.context.__parent__
    1679         name = self.context.__name__
    1680         self.context = obj
    1681         if hasattr(parent, name):
    1682             setattr(parent, name, obj)
    1683         else:
    1684             del parent[name]
    1685             parent[name] = obj
    1686             pass
    1687         return
    1688 
    1689 
    1690 #
    1691 # FacultiesContainer pages...
    1692 #
    1693 
    1694 class FacultiesContainerPage(KofaPage):
    1695     """ Index page for faculty containers.
    1696     """
    1697     grok.context(IFacultiesContainer)
    1698     grok.require('waeup.viewAcademics')
    1699     grok.name('index')
    1700     label = _('Academic Section')
    1701     pnav = 1
    1702     grok.template('facultypage')
    1703 
    1704 class FacultiesContainerManageFormPage(KofaEditFormPage):
    1705     """Manage the basic properties of a `Faculty` instance.
    1706     """
    1707     grok.context(IFacultiesContainer)
    1708     grok.name('manage')
    1709     grok.require('waeup.manageAcademics')
    1710     grok.template('facultiescontainermanagepage')
    1711     pnav = 1
    1712     taboneactions = [_('Add faculty'), _('Remove selected'),_('Cancel')]
    1713     subunits = _('Faculties')
    1714 
    1715     @property
    1716     def label(self):
    1717         return _('Manage academic section')
    1718 
    1719     @jsaction(_('Remove selected'))
    1720     def delFaculties(self, **data):
    1721         if not checkPermission('waeup.managePortal', self.context):
    1722             self.flash(_('You are not allowed to remove entire faculties.'),
    1723                        type='warning')
    1724             return
    1725         delSubobjects(self, redirect='@@manage', tab='1')
    1726         return
    1727 
    1728     @action(_('Add faculty'), validator=NullValidator)
    1729     def addFaculty(self, **data):
    1730         self.redirect(self.url(self.context, '@@add'))
    1731         return
    1732 
    1733     @action(_('Cancel'), validator=NullValidator)
    1734     def cancel(self, **data):
    1735         self.redirect(self.url(self.context))
    1736         return
    1737 
    1738 
    1739 class FacultyAddFormPage(KofaAddFormPage):
    1740     """ Page form to add a new faculty to a faculty container.
    1741     """
    1742     grok.context(IFacultiesContainer)
    1743     grok.require('waeup.manageAcademics')
    1744     grok.name('add')
    1745     label = _('Add faculty')
    1746     form_fields = grok.AutoFields(IFaculty)
    1747     pnav = 1
    1748 
    1749     @action(_('Add faculty'), style='primary')
    1750     def addFaculty(self, **data):
    1751         faculty = createObject(u'waeup.Faculty')
    1752         self.applyData(faculty, **data)
    1753         try:
    1754             self.context.addFaculty(faculty)
    1755         except KeyError:
    1756             self.flash(_('The faculty code chosen already exists.'),
    1757                        type='danger')
    1758             return
    1759         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    1760         self.context.__parent__.logger.info(
    1761             '%s - added: %s' % (ob_class, faculty.code))
    1762         self.redirect(self.url(self.context, u'@@manage')+'#tab1')
    1763         return
    1764 
    1765     @action(_('Cancel'), validator=NullValidator)
    1766     def cancel(self, **data):
    1767         self.redirect(self.url(self.context))
    1768 
    1769 #
    1770 # Faculty pages
    1771 #
    1772 class FacultyPage(KofaPage):
    1773     """Index page of faculties.
    1774     """
    1775     grok.context(IFaculty)
    1776     grok.require('waeup.viewAcademics')
    1777     grok.name('index')
    1778     pnav = 1
    1779 
    1780     @property
    1781     def label(self):
    1782         return _('Departments')
    1783 
    1784 class FacultyManageFormPage(KofaEditFormPage,
    1785                             LocalRoleAssignmentUtilityView):
    1786     """Manage the basic properties of a `Faculty` instance.
    1787     """
    1788     grok.context(IFaculty)
    1789     grok.name('manage')
    1790     grok.require('waeup.manageAcademics')
    1791     grok.template('facultymanagepage')
    1792     pnav = 1
    1793     subunits = _('Departments')
    1794     taboneactions = [_('Save'),_('Cancel')]
    1795     tabtwoactions = [_('Add department'), _('Remove selected'),_('Cancel')]
    1796     tabthreeactions1 = [_('Remove selected local roles')]
    1797     tabthreeactions2 = [_('Add local role')]
    1798 
    1799     form_fields = grok.AutoFields(IFaculty).omit('code')
    1800 
    1801     @property
    1802     def label(self):
    1803         return _('Manage faculty')
    1804 
    1805     @jsaction(_('Remove selected'))
    1806     def delDepartments(self, **data):
    1807         if not checkPermission('waeup.managePortal', self.context):
    1808             self.flash(_('You are not allowed to remove entire departments.'),
    1809                        type='danger')
    1810             return
    1811         delSubobjects(self, redirect='@@manage', tab='2')
    1812         return
    1813 
    1814     @action(_('Save'), style='primary')
    1815     def save(self, **data):
    1816         return msave(self, **data)
    1817 
    1818     @action(_('Cancel'), validator=NullValidator)
    1819     def cancel(self, **data):
    1820         self.redirect(self.url(self.context))
    1821         return
    1822 
    1823     @action(_('Add department'), validator=NullValidator)
    1824     def addSubunit(self, **data):
    1825         self.redirect(self.url(self.context, '@@add'))
    1826         return
    1827 
    1828     @action(_('Add local role'), validator=NullValidator)
    1829     def addLocalRole(self, **data):
    1830         return add_local_role(self,3,**data)
    1831 
    1832     @action(_('Remove selected local roles'))
    1833     def delLocalRoles(self, **data):
    1834         return del_local_roles(self,3,**data)
    1835 
    1836 class FindStudentsPage(KofaPage):
    1837     """Search students in faculty.
    1838     """
    1839     grok.context(IFaculty)
    1840     grok.name('find_students')
    1841     grok.require('waeup.showStudents')
    1842     grok.template('findstudentspage')
    1843     search_button = _('Find student(s)')
    1844     pnav = 1
    1845 
    1846     @property
    1847     def label(self):
    1848         return _('Find students in ') + ('%s' % self.context.longtitle)
    1849 
    1850     def _find_students(self,query=None, searchtype=None, view=None):
    1851         hitlist = []
    1852         if searchtype in ('fullname',):
    1853             results = Query().searchResults(
    1854                 Text(('students_catalog', searchtype), query) &
    1855                 Eq(('students_catalog', 'faccode'), self.context.code)
    1856                 )
    1857         else:
    1858             results = Query().searchResults(
    1859                 Eq(('students_catalog', searchtype), query) &
    1860                 Eq(('students_catalog', 'faccode'), self.context.code)
    1861                 )
    1862         for result in results:
    1863             hitlist.append(StudentQueryResultItem(result, view=view))
    1864         return hitlist
    1865 
    1866     def update(self, *args, **kw):
    1867         form = self.request.form
    1868         self.hitlist = []
    1869         if 'searchterm' in form and form['searchterm']:
    1870             self.searchterm = form['searchterm']
    1871             self.searchtype = form['searchtype']
    1872         elif 'old_searchterm' in form:
    1873             self.searchterm = form['old_searchterm']
    1874             self.searchtype = form['old_searchtype']
    1875         else:
    1876             if 'search' in form:
    1877                 self.flash(_('Empty search string'), type='warning')
    1878             return
    1879         self.hitlist = self._find_students(query=self.searchterm,
    1880             searchtype=self.searchtype, view=self)
    1881         if not self.hitlist:
    1882             self.flash(_('No student found.'), type='warning')
    1883         return
    1884 
    1885 class DepartmentAddFormPage(KofaAddFormPage):
    1886     """Add a department to a faculty.
    1887     """
    1888     grok.context(IFaculty)
    1889     grok.name('add')
    1890     grok.require('waeup.manageAcademics')
    1891     label = _('Add department')
    1892     form_fields = grok.AutoFields(IDepartment)
    1893     pnav = 1
    1894 
    1895     @action(_('Add department'), style='primary')
    1896     def addDepartment(self, **data):
    1897         department = createObject(u'waeup.Department')
    1898         self.applyData(department, **data)
    1899         try:
    1900             self.context.addDepartment(department)
    1901         except KeyError:
    1902             self.flash(_('The code chosen already exists in this faculty.'),
    1903                        type='danger')
    1904             return
    1905         self.status = self.flash(
    1906             _("Department ${a} added.", mapping = {'a':data['code']}))
    1907         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    1908         self.context.__parent__.__parent__.logger.info(
    1909             '%s - added: %s' % (ob_class, data['code']))
    1910         self.redirect(self.url(self.context, u'@@manage')+'#tab2')
    1911         return
    1912 
    1913     @action(_('Cancel'), validator=NullValidator)
    1914     def cancel(self, **data):
    1915         self.redirect(self.url(self.context))
    1916         return
    1917 
    1918 #
    1919 # Department pages
    1920 #
    1921 class DepartmentPage(KofaPage):
    1922     """Department index page.
    1923     """
    1924     grok.context(IDepartment)
    1925     grok.require('waeup.viewAcademics')
    1926     grok.name('index')
    1927     pnav = 1
    1928     label = _('Courses and Certificates')
    1929 
    1930     def update(self):
    1931         super(DepartmentPage, self).update()
    1932         return
    1933 
    1934     def getCourses(self):
    1935         """Get a list of all stored courses.
    1936         """
    1937         for key, val in self.context.courses.items():
    1938             url = self.url(val)
    1939             yield(dict(url=url, name=key, container=val))
    1940 
    1941     def getCertificates(self):
    1942         """Get a list of all stored certificates.
    1943         """
    1944         for key, val in self.context.certificates.items():
    1945             url = self.url(val)
    1946             yield(dict(url=url, name=key, container=val))
    1947 
    1948 class DepartmentManageFormPage(KofaEditFormPage,
    1949                                LocalRoleAssignmentUtilityView):
    1950     """Manage the basic properties of a `Department` instance.
    1951     """
    1952     grok.context(IDepartment)
    1953     grok.name('manage')
    1954     grok.require('waeup.manageAcademics')
    1955     pnav = 1
    1956     grok.template('departmentmanagepage')
    1957     taboneactions = [_('Save'),_('Cancel')]
    1958     tabtwoactions = [_('Add course'), _('Remove selected courses'),_('Cancel')]
    1959     tabthreeactions = [_('Add certificate'), _('Remove selected certificates'),
    1960                        _('Cancel')]
    1961     tabfouractions1 = [_('Remove selected local roles')]
    1962     tabfouractions2 = [_('Add local role')]
    1963 
    1964     form_fields = grok.AutoFields(IDepartment).omit('code')
    1965 
    1966     @property
    1967     def label(self):
    1968         return _('Manage department')
    1969 
    1970     def getCourses(self):
    1971         """Get a list of all stored courses.
    1972         """
    1973         for key, val in self.context.courses.items():
    1974             url = self.url(val)
    1975             yield(dict(url=url, name=key, container=val))
    1976 
    1977     def getCertificates(self):
    1978         """Get a list of all stored certificates.
    1979         """
    1980         for key, val in self.context.certificates.items():
    1981             url = self.url(val)
    1982             yield(dict(url=url, name=key, container=val))
    1983 
    1984     @action(_('Save'), style='primary')
    1985     def save(self, **data):
    1986         return msave(self, **data)
    1987 
    1988     @jsaction(_('Remove selected courses'))
    1989     def delCourses(self, **data):
    1990         delSubobjects(
    1991             self, redirect='@@manage', tab='2', subcontainer='courses')
    1992         return
    1993 
    1994     @jsaction(_('Remove selected certificates'))
    1995     def delCertificates(self, **data):
    1996         if not checkPermission('waeup.managePortal', self.context):
    1997             self.flash(_('You are not allowed to remove certificates.'),
    1998                        type='warning')
    1999             return
    2000         delSubobjects(
    2001             self, redirect='@@manage', tab='3', subcontainer='certificates')
    2002         return
    2003 
    2004     @action(_('Add course'), validator=NullValidator)
    2005     def addCourse(self, **data):
    2006         self.redirect(self.url(self.context, 'addcourse'))
    2007         return
    2008 
    2009     @action(_('Add certificate'), validator=NullValidator)
    2010     def addCertificate(self, **data):
    2011         self.redirect(self.url(self.context, 'addcertificate'))
    2012         return
    2013 
    2014     @action(_('Cancel'), validator=NullValidator)
    2015     def cancel(self, **data):
    2016         self.redirect(self.url(self.context))
    2017         return
    2018 
    2019     @action(_('Add local role'), validator=NullValidator)
    2020     def addLocalRole(self, **data):
    2021         return add_local_role(self,4,**data)
    2022 
    2023     @action(_('Remove selected local roles'))
    2024     def delLocalRoles(self, **data):
    2025         return del_local_roles(self,4,**data)
    2026 
    2027 class CourseAddFormPage(KofaAddFormPage):
    2028     """Add-form to add course to a department.
    2029     """
    2030     grok.context(IDepartment)
    2031     grok.name('addcourse')
    2032     grok.require('waeup.manageAcademics')
    2033     label = _(u'Add course')
    2034     form_fields = grok.AutoFields(ICourse)
    2035     pnav = 1
    2036 
    2037     @action(_('Add course'))
    2038     def addCourse(self, **data):
    2039         course = createObject(u'waeup.Course')
    2040         self.applyData(course, **data)
    2041         try:
    2042             self.context.courses.addCourse(course)
    2043         except DuplicationError, error:
    2044             # signals duplication error
    2045             entries = error.entries
    2046             for entry in entries:
    2047                 # do not use error.msg but render a more detailed message instead
    2048                 # and show links to all certs with same code
    2049                 message = _('A course with same code already exists: ')
    2050                 message += '<a href="%s">%s</a>' % (
    2051                     self.url(entry), getattr(entry, '__name__', u'Unnamed'))
    2052                 self.flash(message, type='warning')
    2053             self.redirect(self.url(self.context, u'@@addcourse'))
    2054             return
    2055         message = _(u'Course ${a} successfully created.', mapping = {'a':course.code})
    2056         self.flash(message)
    2057         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    2058         self.context.__parent__.__parent__.__parent__.logger.info(
    2059             '%s - added: %s' % (ob_class, data['code']))
    2060         self.redirect(self.url(self.context, u'@@manage')+'#tab2')
    2061         return
    2062 
    2063     @action(_('Cancel'), validator=NullValidator)
    2064     def cancel(self, **data):
    2065         self.redirect(self.url(self.context))
    2066         return
    2067 
    2068 class CertificateAddFormPage(KofaAddFormPage):
    2069     """Add-form to add certificate to a department.
    2070     """
    2071     grok.context(IDepartment)
    2072     grok.name('addcertificate')
    2073     grok.require('waeup.manageAcademics')
    2074     label = _(u'Add certificate')
    2075     form_fields = grok.AutoFields(ICertificate)
    2076     pnav = 1
    2077 
    2078     @action(_('Add certificate'))
    2079     def addCertificate(self, **data):
    2080         certificate = createObject(u'waeup.Certificate')
    2081         self.applyData(certificate, **data)
    2082         try:
    2083             self.context.certificates.addCertificate(certificate)
    2084         except DuplicationError, error:
    2085             # signals duplication error
    2086             entries = error.entries
    2087             for entry in entries:
    2088                 # do not use error.msg but render a more detailed message instead
    2089                 # and show links to all certs with same code
    2090                 message = _('A certificate with same code already exists: ')
    2091                 message += '<a href="%s">%s</a>' % (
    2092                     self.url(entry), getattr(entry, '__name__', u'Unnamed'))
    2093                 self.flash(message, type='warning')
    2094             self.redirect(self.url(self.context, u'@@addcertificate'))
    2095             return
    2096         message = _(u'Certificate ${a} successfully created.', mapping = {'a':certificate.code})
    2097         self.flash(message)
    2098         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    2099         self.context.__parent__.__parent__.__parent__.logger.info(
    2100             '%s - added: %s' % (ob_class, data['code']))
    2101         self.redirect(self.url(self.context, u'@@manage')+'#tab3')
    2102         return
    2103 
    2104     @action(_('Cancel'), validator=NullValidator)
    2105     def cancel(self): #, **data):
    2106         self.redirect(self.url(self.context))
    2107         return
    2108 
    2109 #
    2110 # Courses pages
    2111 #
    2112 class CoursePage(KofaDisplayFormPage):
    2113     """Course index page.
    2114     """
    2115     grok.context(ICourse)
    2116     grok.name('index')
    2117     grok.require('waeup.viewAcademics')
    2118     pnav = 1
    2119     form_fields = grok.AutoFields(ICourse)
    2120 
    2121     @property
    2122     def label(self):
    2123         return '%s (%s)' % (self.context.title, self.context.code)
    2124 
    2125 class CourseManageFormPage(KofaEditFormPage,
    2126                            LocalRoleAssignmentUtilityView):
    2127     """Edit form page for courses.
    2128     """
    2129     grok.context(ICourse)
    2130     grok.name('manage')
    2131     grok.require('waeup.manageAcademics')
    2132     grok.template('coursemanagepage')
    2133     label = _(u'Edit course')
    2134     pnav = 1
    2135     taboneactions = [_('Save'),_('Cancel')]
    2136     tabtwoactions1 = [_('Remove selected local roles')]
    2137     tabtwoactions2 = [_('Add local role')]
    2138 
    2139     form_fields = grok.AutoFields(ICourse).omit('code')
    2140 
    2141     @action(_('Save'), style='primary')
    2142     def save(self, **data):
    2143         return msave(self, **data)
    2144 
    2145     @action(_('Cancel'), validator=NullValidator)
    2146     def cancel(self, **data):
    2147         self.redirect(self.url(self.context))
    2148         return
    2149 
    2150     @action(_('Add local role'), validator=NullValidator)
    2151     def addLocalRole(self, **data):
    2152         return add_local_role(self,2,**data)
    2153 
    2154     @action(_('Remove selected local roles'))
    2155     def delLocalRoles(self, **data):
    2156         return del_local_roles(self,2,**data)
    2157 
    2158 #
    2159 # Certificate pages
    2160 #
    2161 class CertificatePage(KofaDisplayFormPage):
    2162     """Index page for certificates.
    2163     """
    2164     grok.context(ICertificate)
    2165     grok.name('index')
    2166     grok.require('waeup.viewAcademics')
    2167     pnav = 1
    2168     form_fields = grok.AutoFields(ICertificate)
    2169     grok.template('certificatepage')
    2170 
    2171     @property
    2172     def label(self):
    2173         return "%s (%s)" % (self.context.title, self.context.code)
    2174 
    2175     def update(self):
    2176         return super(CertificatePage, self).update()
    2177 
    2178 class CertificateManageFormPage(KofaEditFormPage,
    2179                                 LocalRoleAssignmentUtilityView):
    2180     """Manage the properties of a `Certificate` instance.
    2181     """
    2182     grok.context(ICertificate)
    2183     grok.name('manage')
    2184     grok.require('waeup.manageAcademics')
    2185     pnav = 1
    2186     label = _('Edit certificate')
    2187 
    2188     form_fields = grok.AutoFields(ICertificate).omit('code')
    2189 
    2190     pnav = 1
    2191     grok.template('certificatemanagepage')
    2192     taboneactions = [_('Save'),_('Cancel')]
    2193     tabtwoactions = [_('Add certificate course'),
    2194                      _('Remove selected certificate courses'),_('Cancel')]
    2195     tabthreeactions1 = [_('Remove selected local roles')]
    2196     tabthreeactions2 = [_('Add local role')]
    2197 
    2198     @property
    2199     def label(self):
    2200         return _('Manage certificate')
    2201 
    2202     @action(_('Save'), style='primary')
    2203     def save(self, **data):
    2204         return msave(self, **data)
    2205 
    2206     @jsaction(_('Remove selected certificate courses'))
    2207     def delCertificateCourses(self, **data):
    2208         delSubobjects(self, redirect='@@manage', tab='2')
    2209         return
    2210 
    2211     @action(_('Add certificate course'), validator=NullValidator)
    2212     def addCertificateCourse(self, **data):
    2213         self.redirect(self.url(self.context, 'addcertificatecourse'))
    2214         return
    2215 
    2216     @action(_('Cancel'), validator=NullValidator)
    2217     def cancel(self, **data):
    2218         self.redirect(self.url(self.context))
    2219         return
    2220 
    2221     @action(_('Add local role'), validator=NullValidator)
    2222     def addLocalRole(self, **data):
    2223         return add_local_role(self,3,**data)
    2224 
    2225     @action(_('Remove selected local roles'))
    2226     def delLocalRoles(self, **data):
    2227         return del_local_roles(self,3,**data)
    2228 
    2229 
    2230 class CertificateCourseAddFormPage(KofaAddFormPage):
    2231     """Add-page to add a course ref to a certificate
    2232     """
    2233     grok.context(ICertificate)
    2234     grok.name('addcertificatecourse')
    2235     grok.require('waeup.manageAcademics')
    2236     form_fields = grok.AutoFields(ICertificateCourse)
    2237     pnav = 1
    2238     label = _('Add certificate course')
    2239 
    2240     @action(_('Add certificate course'))
    2241     def addCertcourse(self, **data):
    2242         try:
    2243             self.context.addCertCourse(**data)
    2244         except KeyError:
    2245             self.status = self.flash(_('The chosen certificate course is already '
    2246                                   'part of this certificate.'), type='warning')
    2247             return
    2248         self.status = self.flash(
    2249             _("certificate course ${a}_${b} added.",
    2250             mapping = {'a': data['course'].code, 'b': data['level']}))
    2251         code = "%s_%s" % (data['course'].code, data['level'])
    2252         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    2253         grok.getSite().logger.info('%s - added: %s' % (ob_class, code))
    2254         self.redirect(self.url(self.context, u'@@manage')+'#tab2')
    2255         return
    2256 
    2257     @action(_('Cancel'), validator=NullValidator)
    2258     def cancel(self, **data):
    2259         self.redirect(self.url(self.context))
    2260         return
    2261 
    2262 
    2263 #
    2264 # Certificate course pages...
    2265 #
    2266 class CertificateCoursePage(KofaPage):
    2267     """CertificateCourse index page.
    2268     """
    2269     grok.context(ICertificateCourse)
    2270     grok.name('index')
    2271     grok.require('waeup.viewAcademics')
    2272     pnav = 1
    2273     #form_fields = grok.AutoFields(ICertificateCourse)
    2274 
    2275     @property
    2276     def label(self):
    2277         return '%s' % (self.context.longtitle)
    2278 
    2279     @property
    2280     def leveltitle(self):
    2281         return course_levels.getTerm(self.context.level).title
    2282 
    2283 class CertificateCourseManageFormPage(KofaEditFormPage):
    2284     """Manage the basic properties of a `CertificateCourse` instance.
    2285     """
    2286     grok.context(ICertificateCourse)
    2287     grok.name('manage')
    2288     grok.require('waeup.manageAcademics')
    2289     form_fields = grok.AutoFields(ICertificateCourse).omit('code')
    2290     label = _('Edit certificate course')
    2291     pnav = 1
    2292 
    2293     @action(_('Save and return'), style='primary')
    2294     def saveAndReturn(self, **data):
    2295         parent = self.context.__parent__
    2296         if self.context.level == data['level']:
    2297             msave(self, **data)
    2298         else:
    2299             # The level changed. We have to create a new certcourse as
    2300             # the key of the entry will change as well...
    2301             old_level = self.context.level
    2302             data['course'] = self.context.course
    2303             parent.addCertCourse(**data)
    2304             parent.delCertCourses(data['course'].code, level=old_level)
    2305             self.flash(_('Form has been saved.'))
    2306             old_code = "%s_%s" % (data['course'].code, old_level)
    2307             new_code = "%s_%s" % (data['course'].code, data['level'])
    2308             ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    2309             grok.getSite().logger.info(
    2310                 '%s - renamed: %s to %s' % (ob_class, old_code, new_code))
    2311         self.redirect(self.url(parent))
    2312         return
    2313 
    2314     @action(_('Cancel'), validator=NullValidator)
    2315     def cancel(self, **data):
    2316         self.redirect(self.url(self.context))
    2317         return
    2318 
    23191567class ChangePasswordRequestPage(KofaForm):
    23201568    """Captcha'd page for all kind of users to request a password change.
     
    23351583
    23361584    def _searchUser(self, identifier, email):
    2337         # Search student
    2338         cat = queryUtility(ICatalog, name='students_catalog')
    2339         results = cat.searchResults(
     1585        # Search customer
     1586        #cat = queryUtility(ICatalog, name='customers_catalog')
     1587        #results = cat.searchResults(
    23401588            #reg_number=(identifier, identifier),
    2341             email=(email,email))
    2342         for result in results:
    2343             if result.student_id == identifier or \
    2344                 result.reg_number == identifier or \
    2345                 result.matric_number == identifier:
    2346                 return result
    2347         # Search applicant
    2348         cat = queryUtility(ICatalog, name='applicants_catalog')
    2349         if cat is not None:
    2350             results = cat.searchResults(
    2351                 #reg_number=(identifier, identifier),
    2352                 email=(email,email))
    2353             for result in results:
    2354                 if result.applicant_id == identifier or \
    2355                     result.reg_number == identifier:
    2356                     return result
     1589        #    email=(email,email))
     1590        #for result in results:
     1591        #    if result.student_id == identifier or \
     1592        #        result.reg_number == identifier or \
     1593        #        result.matric_number == identifier:
     1594        #        return result
    23571595        # Search portal user
    23581596        user = grok.getSite()['users'].get(identifier, None)
     
    23671605            # No need to flash something.
    23681606            return
    2369         # Search student or applicant
     1607        # Search customer
    23701608        identifier = data['identifier']
    23711609        email = data['email']
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/pdf.py

    r10595 r11947  
    566566
    567567    @classmethod
    568     def _addCourse(cls, table_data, row_num, course_label, course_link,
    569                    lang, domain):
    570         """Add course data to `table_data`.
    571         """
    572         if not course_label or not course_link:
    573             return table_data, row_num
    574         f_label= translate(
    575             _(course_label), domain, target_language=lang)
    576         f_label = Paragraph(f_label, ENTRY1_STYLE)
    577         f_text = Paragraph(course_link, ENTRY1_STYLE)
    578         table_data.append([f_label, f_text])
    579         row_num += 1
    580         return table_data, row_num
    581 
    582     @classmethod
    583     def _addDeptAndFaculty(cls, table_data, row_num, dept, faculty,
    584                            lang, domain):
    585         """Add `dept` and `faculty` as table rows to `table_data`.
    586 
    587         `dept` and `faculty` are expected to be strings or None. In
    588         latter case they are not put into the table.
    589         """
    590         for label, text in (('Department:', dept), ('Faculty:', faculty)):
    591             if text is None:
    592                 continue
    593             label = translate(_(label), domain, target_language=lang)
    594             table_data.append([
    595                 Paragraph(label, ENTRY1_STYLE),
    596                 Paragraph(text, ENTRY1_STYLE)])
    597             row_num += 1
    598         return table_data, row_num
    599 
    600     @classmethod
    601568    def _drawSignatureBoxes(cls, canvas, width, height, signatures=[]):
    602569        """Draw signature boxes into canvas.
     
    661628    def getWidgetsTable(self, form_fields, context, view, lang='en',
    662629                        domain='waeup.kofa', separators=None,
    663                         course_label=None, course_link=None, dept=None,
    664                         faculty=None, colWidths=None, twoDataCols=False):
     630                        colWidths=None, twoDataCols=False):
    665631        """Return a reportlab `Table` instance, created from widgets
    666632        determined by `form_fields` and `context`.
     
    679645        - `separators`
    680646           a list of separators.
    681         - `course_label` and `course_link`
    682            if a course should be added to the table, `course_label`
    683            and `course_link` can be given, both being strings. They
    684            will be rendered in an extra-row.
    685         - `dept` and `faculty`
    686            if these are given, we render extra rows with faculty and
    687            department.
    688647        - `colWidths`
    689648           defines the the column widths of the data in the right column
     
    699658        table_data, row_num = self._getWidgetsTableData(
    700659            widgets, separators, domain, lang, twoDataCols)
    701 
    702         # Add course (admitted, etc.) if applicable
    703         table_data, row_num = self._addCourse(
    704             table_data, row_num, course_label, course_link, lang, domain,)
    705 
    706         ## Add dept. and faculty if applicable
    707         table_data, row_num = self._addDeptAndFaculty(
    708             table_data, row_num, dept, faculty, lang, domain)
    709660
    710661        # render two-column table of tables if applicable
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/templates/datacenterexportpage.pt

    r11826 r11947  
    3434  </div>
    3535</form>
    36 
    37 <br />
    38 
    39 <p i18n:translate="">
    40   Student data exports have to be further configured. You can create CSV files
    41   on the <a href="@@exportconfig">student data export configuration page</a>.
    42 </p>
    4336
    4437<br /><br />
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/templates/default_waeup_edit_form.pt

    r7737 r11947  
    55    <tbody>
    66      <tal:widgets content="structure provider:widgets" />
    7       <tal:files content="structure provider:files" />
    87    </tbody>
    98  </table>
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/templates/staffsitelayout.pt

    r11463 r11947  
    7373
    7474    <!-- Diazo element-->
    75     <span tal:condition="layout/getStudentName">
    76       <div class="wfstatus">
    77             <span tal:replace="python:context.student.student_id">
    78               Id
    79             </span>
    80             &bull;
    81             <span tal:replace="python:context.student.translated_state">
    82               State
    83             </span>
    84       </div>
    85     </span>
    86     <!-- /Diazo element-->
    87 
    88     <!-- Diazo element-->
    8975    <div class="sidebar well">
    90         <div tal:condition="layout/getStudentName">
    91           <div class="kofa-sidebar-title" tal:content="layout/getStudentName">STUDENTNAME</div>
    92           <ul class="nav">
    93             <tal:left content="structure provider:left_studentmanage" />
    94           </ul>
    95         </div>
    9676        <div tal:condition="layout/isAuthenticated">
    9777          <div class="kofa-sidebar-title" tal:content="layout/getUserTitle">USERNAME</div>
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/templates/studentsitelayout.pt

    r11463 r11947  
    3030    <ul class="nav kofa-navbar-left">
    3131        <tal:primary_nav content="structure provider:primary_nav" />
    32         <tal:primary_nav content="structure provider:primary_nav_student" />
    3332    </ul>
    3433    <!-- /Diazo element-->
     
    7271
    7372    <!-- Diazo element-->
    74     <span tal:condition="layout/getStudentName">
    75       <div class="wfstatus">
    76             <span tal:replace="python:context.student.student_id">
    77               Id
    78             </span>
    79             &bull;
    80             <span tal:replace="python:context.student.translated_state">
    81               State
    82             </span>
    83       </div>
    84     </span>
    85     <!-- /Diazo element-->
    86 
    87     <!-- Diazo element-->
    8873    <div class="kofa-content">
    8974      <div class="actionbar" tal:condition="provider:actionbar">
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/templates/usereditformpage.pt

    r11254 r11947  
    1818        </td>
    1919      </tr>
    20       <tal:files content="structure provider:files" />
    2120    </tbody>
    2221  </table>
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/tests/test_permissions.py

    r8920 r11947  
    3838manager_pages = [
    3939    # The pages that should only be accessible by manager...
    40     '/@@manage', '/@@administration', '/faculties/@@search',
     40    '/@@manage', '/@@administration',
    4141    '/users/@@index', '/users/@@add', '/users/alice/@@manage',
    4242    '/datacenter/@@index', '/datacenter/@@upload', '/datacenter/@@import1',
    4343    '/datacenter/@@import2', '/datacenter/@@import3', '/datacenter/@@import4',
    4444    '/datacenter/@@logs', '/datacenter/@@show', '/datacenter/@@manage',
    45     '/faculties/@@index', '/faculties/@@add', '/faculties/@@manage',
    46     '/faculties/fac1/@@index', '/faculties/fac1/@@manage',
    47     '/faculties/fac1/@@add',
    48     '/faculties/fac1/dept1/@@index',
    49     '/faculties/fac1/dept1/@@manage',
    50     '/faculties/fac1/dept1/@@addcourse',
    51     '/faculties/fac1/dept1/@@addcertificate',
    52     '/faculties/fac1/dept1/courses/crs1/@@index',
    53     '/faculties/fac1/dept1/courses/crs1/@@manage',
    54     '/faculties/fac1/dept1/certificates/cert1/@@index',
    55     '/faculties/fac1/dept1/certificates/cert1/@@manage',
    56     '/faculties/fac1/dept1/certificates/cert1/@@addcertificatecourse',
    57     '/faculties/fac1/dept1/certificates/cert1/crs1_100/@@index',
    58     '/faculties/fac1/dept1/certificates/cert1/crs1_100/@@manage',
    5945    ]
    6046public_pages = [
     
    7965        app['datacenter'].setStoragePath(self.dc_root)
    8066        app['users'].addUser('alice', 'alice')
    81         fac1 = createObject('waeup.Faculty')
    82         fac1.code = "fac1"
    83         app['faculties'].addFaculty(fac1)
    84         dept = createObject('waeup.Department')
    85         dept.code = 'dept1'
    86         fac1.addDepartment(dept)
    87         course = createObject('waeup.Course')
    88         course.code = 'crs1'
    89         dept.courses.addCourse(course)
    90         cert = createObject('waeup.Certificate')
    91         cert.code = 'cert1'
    92         dept.certificates.addCertificate(cert)
    93         cert.addCertCourse(course)
    9467
    9568        self.browser = Browser()
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/browser/viewlets.py

    r11862 r11947  
    2424from zope.traversing.browser import absoluteURL
    2525from waeup.kofa.browser.pages import (
    26     UniversityPage, FacultiesContainerPage, DatacenterPage, FacultyPage,
    27     DepartmentPage, CoursePage, CertificatePage, CertificateCoursePage,
     26    UniversityPage, DatacenterPage,
    2827    UsersContainerPage, UserManageFormPage)
    2928from waeup.kofa.browser.interfaces import (
    30     IFacultiesContainer, IFaculty, IDepartment, ICourse, ICertificate,
    31     ICertificateCourse, IBreadcrumbContainer, IUniversity, IUsersContainer)
     29    IBreadcrumbContainer, IUniversity, IUsersContainer)
    3230from waeup.kofa.interfaces import (
    3331    IKofaUtils, IKofaObject, IKofaXMLExporter,
     
    399397    grok.order(1)
    400398
    401 class ManageFacultiesContainerActionButton(ManageActionButton):
    402     """ 'Manage settings' button for faculties.
    403     """
    404     grok.context(IFacultiesContainer)
    405     grok.view(FacultiesContainerPage)
    406     text = _('Manage academic section')
    407 
    408 class ExportFacultiesStudentsActionButton(ManageActionButton):
    409     """ 'Export student data' button for faculties.
    410     """
    411     grok.context(IFacultiesContainer)
    412     grok.view(FacultiesContainerPage)
    413     grok.name('exportfacultystudents')
    414     grok.require('waeup.showStudents')
    415     icon = 'actionicon_down.png'
    416     text = _('Export student data')
    417     target = 'exports'
    418     grok.order(3)
    419 
    420 class SearchFacultiesContainerActionButton(ManageActionButton):
    421     """ 'Manage settings' button for faculties.
    422     """
    423     grok.context(IFacultiesContainer)
    424     grok.view(FacultiesContainerPage)
    425     text = _('Search academic section')
    426     icon = 'actionicon_search.png'
    427     target = '@@search'
    428    
    429 class ManageFacultyActionButton(ManageActionButton):
    430     """ 'Manage settings' button for faculties.
    431     """
    432     grok.context(IFaculty)
    433     grok.view(FacultyPage)
    434     text = _('Manage faculty')
    435 
    436 class StudentSearchActionButton(ManageActionButton):
    437     grok.order(2)
    438     grok.context(IFaculty)
    439     grok.view(FacultyPage)
    440     grok.name('findstudents')
    441     grok.require('waeup.showStudents')
    442     text = _('Find students')
    443     icon = 'actionicon_search.png'
    444     target = 'find_students'
    445 
    446 class ManageDepartmentActionButton(ManageActionButton):
    447     """ 'Manage settings' button for departments.
    448     """
    449     grok.context(IDepartment)
    450     grok.view(DepartmentPage)
    451     text = _('Manage department')
    452     grok.order(1)
    453 
    454 class ShowDepartmentStudentsActionButton(ManageActionButton):
    455     """ 'Show students' button for departments.
    456     """
    457     grok.context(IDepartment)
    458     grok.view(DepartmentPage)
    459     grok.name('showdepartmentstudents')
    460     grok.require('waeup.showStudents')
    461     icon = 'actionicon_student.png'
    462     text = _('Show students')
    463     target = 'students'
    464     grok.order(2)
    465 
    466 class ExportDepartmentStudentsActionButton(ManageActionButton):
    467     """ 'Export student data' button for departments.
    468     """
    469     grok.context(IDepartment)
    470     grok.view(DepartmentPage)
    471     grok.name('exportdepartmentstudents')
    472     grok.require('waeup.showStudents')
    473     icon = 'actionicon_down.png'
    474     text = _('Export student data')
    475     target = 'exports'
    476     grok.order(3)
    477 
    478 class ClearDepartmentStudentsActionButton(ManageActionButton):
    479     """ 'Clear all students' button for departments.
    480     """
    481     grok.context(IDepartment)
    482     grok.view(DepartmentPage)
    483     grok.name('cleardepartmentstudents')
    484     grok.require('waeup.clearAllStudents')
    485     icon = 'actionicon_accept.png'
    486     text = _('Clear all students')
    487     target = 'clearallstudents'
    488     grok.order(4)
    489 
    490     @property
    491     def onclick(self):
    492         return "return window.confirm(%s);" % _(
    493             "'All students, who requested clearance in this department, will be cleared. Are you sure?'")
    494 
    495 class ManageCourseActionButton(ManageActionButton):
    496     """ 'Edit settings' button for courses.
    497     """
    498     grok.context(ICourse)
    499     grok.view(CoursePage)
    500     text = _('Edit course')
    501     grok.order(1)
    502    
    503 class ShowCourseStudentsActionButton(ManageActionButton):
    504     """ 'Show students' button in course.
    505     """
    506     grok.context(ICourse)
    507     grok.view(CoursePage)
    508     grok.name('showcoursestudents')
    509     grok.require('waeup.showStudents')
    510     icon = 'actionicon_student.png'
    511     text = _('Show students')
    512     target = 'students'
    513     grok.order(2)
    514 
    515 class ExportCourseStudentsActionButton(ManageActionButton):
    516     """ 'Export student data' button for courses.
    517     """
    518     grok.context(ICourse)
    519     grok.view(CoursePage)
    520     grok.name('exportcoursestudents')
    521     grok.require('waeup.showStudents')
    522     icon = 'actionicon_down.png'
    523     text = _('Export student data')
    524     target = 'exports'
    525     grok.order(3)
    526 
    527 class UpdateScoresActionButton(ManageActionButton):
    528     """ 'Update scores' button in course.
    529     """
    530     grok.context(ICourse)
    531     grok.view(CoursePage)
    532     grok.name('updatescores')
    533     grok.require('waeup.editScores')
    534     icon = 'actionicon_scores.png'
    535     text = _('Update scores')
    536     target = 'edit_scores'
    537     grok.order(4)
    538 
    539 class ManageCertificateActionButton(ManageActionButton):
    540     """ 'Manage settings' button for certificates.
    541     """
    542     grok.context(ICertificate)
    543     grok.view(CertificatePage)
    544     text = _('Manage certificate')
    545     grok.order(1)
    546 
    547 class ShowCertificateStudentsActionButton(ManageActionButton):
    548     """ 'Show students' button for certificates.
    549     """
    550     grok.context(ICertificate)
    551     grok.view(CertificatePage)
    552     grok.name('showcertificatestudents')
    553     grok.require('waeup.showStudents')
    554     icon = 'actionicon_student.png'
    555     text = _('Show students')
    556     target = 'students'
    557     grok.order(2)
    558 
    559 class ExportCertificateStudentsActionButton(ManageActionButton):
    560     """ 'Export student data' button for certificates.
    561     """
    562     grok.context(ICertificate)
    563     grok.view(CertificatePage)
    564     grok.name('exportcertificatestudents')
    565     grok.require('waeup.showStudents')
    566     icon = 'actionicon_down.png'
    567     text = _('Export student data')
    568     target = 'exports'
    569     grok.order(3)
    570 
    571 class ManageCertificateCourseActionButton(ManageActionButton):
    572     """ 'Manage settings' button for certificate courses.
    573     """
    574     grok.context(ICertificateCourse)
    575     grok.view(CertificateCoursePage)
    576     text = _('Edit certificate course')
    577 
    578399class AddUserActionButton(AddActionButton):
    579400    grok.require('waeup.manageUsers')
     
    676497#    tab_title = u'Home'
    677498
    678 class FacultiesTab(PrimaryNavTab):
    679     """Faculties-tab in primary navigation.
    680     """
    681     grok.order(2)
    682     grok.require('waeup.viewAcademics')
    683 
    684     pnav = 1
    685     tab_title = _(u'Academics')
    686 
    687     @property
    688     def link_target(self):
    689         return self.view.application_url('faculties')
    690 
    691    
     499
    692500class EnquiriesTab(PrimaryNavTab):
    693501    """Contact tab in primary navigation.
     
    793601        super(SubobjectLister, self).update()
    794602        return
    795 
    796 
    797 class FacultiesContainerListHead(grok.Viewlet):
    798     """The header line of faculty container subobject lists.
    799     """
    800     grok.order(1)
    801     grok.viewletmanager(SubobjectLister)
    802     grok.context(IFacultiesContainer)
    803     grok.require('waeup.viewAcademics')
    804 
    805     def render(self):
    806         return u'<th>Code</th><th>Title</th><th></th>'
    807 
    808 class FacultyListName(grok.Viewlet):
    809     """Display a the title of a faculty as link in a list.
    810     """
    811     grok.order(1)
    812     grok.viewletmanager(SubobjectLister)
    813     grok.context(IFaculty)
    814     grok.require('waeup.viewAcademics')
    815 
    816     def render(self):
    817         return u'<a href="%s">%s</a>' % (
    818             self.view.url(self.context), self.context.__name__)
    819 
    820 class FacultyListTitle(grok.Viewlet):
    821     """Display the title of a faculty in a list.
    822     """
    823     grok.order(2)
    824     grok.viewletmanager(SubobjectLister)
    825     grok.context(IFaculty)
    826     grok.require('waeup.viewAcademics')
    827 
    828     def render(self):
    829         return self.context.title
    830 
    831 class FacultyRemoveButton(grok.Viewlet):
    832     """Render a remove button for faculty lists.
    833     """
    834     grok.order(3)
    835     grok.viewletmanager(SubobjectLister)
    836     grok.context(IFaculty)
    837     grok.require('waeup.manageAcademics')
    838 
    839     def render(self):
    840         return u'<div class="text-right"><form method="POST">' + \
    841             '<input class="text-right" type="submit" value="remove" />' + \
    842             '</form></div>'
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/configuration.py

    r11477 r11947  
    2424from waeup.kofa.interfaces import (
    2525    ISessionConfiguration, IConfigurationContainer, ISessionConfigurationAdd,
    26     academic_sessions_vocab)
     26    application_sessions_vocab)
    2727from waeup.kofa.utils.helpers import attrs_to_fields
    2828
     
    4141                'ConfigurationContainers contain only '
    4242                'ISessionConfiguration instances')
    43         code = unicode(sessionconfiguration.academic_session)
     43        code = unicode(sessionconfiguration.application_session)
    4444        self[code] = sessionconfiguration
    4545        return
     
    5555
    5656    def getSessionString(self):
    57         return academic_sessions_vocab.getTerm(self.academic_session).title
     57        return application_sessions_vocab.getTerm(self.application_session).title
    5858
    5959SessionConfiguration = attrs_to_fields(SessionConfiguration)
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/imagestorage.py

    r11480 r11947  
    2020A few words about storing files with ``waeup.kofa``. The need for this
    2121feature arised initially from the need to store passport files for
    22 applicants and students. These files are dynamic (can be changed
     22customers. These files are dynamic (can be changed
    2323anytime), mean a lot of traffic and cost a lot of memory/disk space.
    2424
     
    9797
    9898The file store supports special handling for certain files. For
    99 example we want applicant images to be stored in a different directory
    100 than student images, etc. Because the file store cannot know all
     99example we want some customer images to be stored in a different directory
     100than other customer images, etc. Because the file store cannot know all
    101101details about these special treatment of certain files, it looks up
    102102helpers (handlers) to provide the information it needs for really
     
    120120
    121121Examples for such a file store handler can be found in the
    122 :mod:`waeup.kofa.applicants.applicant` module. Please see also the
     122:mod:`waeup.kofa.customers.customer` module. Please see also the
    123123:class:`DefaultFileStoreHandler` class below for more details.
    124124
     
    169169
    170170Often the internal filename or file id of a file depends on a
    171 context. For example when we store passport photographs of applicants,
    172 then each image belongs to a certain applicant instance. It is not
    173 difficult to maintain such a connection manually: Say every applicant
     171context. For example when we store passport photographs of customers,
     172then each image belongs to a certain customer instance. It is not
     173difficult to maintain such a connection manually: Say every customer
    174174had an id, then we could put this id into the filename as well and
    175175would build the filename to store/get the connected file by using that
    176176filename. You then would create filenames of a format like this::
    177177
    178   __<MARKER-STRING>__applicant0001
    179 
    180 where ``applicant0001`` would tell exactly which applicant you can see
     178  __<MARKER-STRING>__customer0001
     179
     180where ``customer0001`` would tell exactly which customer you can see
    181181on the photograph. You notice that the internal file id might have
    182182nothing to do with once uploaded filenames. The id above could have
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/interfaces.py

    r11804 r11947  
    8484            SimpleTerm(value, value, title) for title, value in terms])
    8585
    86 def academic_sessions():
     86def application_sessions():
    8787    curr_year = datetime.now().year
    8888    year_range = range(1995, curr_year + 2)
    8989    return [('%s/%s' % (year,year+1), year) for year in year_range]
    9090
    91 academic_sessions_vocab = SimpleKofaVocabulary(*academic_sessions())
     91application_sessions_vocab = SimpleKofaVocabulary(*application_sessions())
    9292
    9393registration_states_vocab = SimpleKofaVocabulary(
     
    145145        return dict(getUtility(IKofaUtils).EXAM_GRADES)[value]
    146146
    147 class DisablePaymentGroupSource(ContextualDictSourceFactoryBase):
    148     """A source for filtering groups of students
    149     """
    150     #: name of dict to deliver from kofa utils.
    151     DICT_NAME = 'DISABLE_PAYMENT_GROUP_DICT'
    152 
    153147# Define a validation method for email addresses
    154148class NotAnEmailAddress(schema.ValidationError):
     
    278272        """Send credentials as email.
    279273
    280         Input is the applicant for which credentials are sent and the
     274        Input is the customer for which credentials are sent and the
    281275        password.
    282276
     
    531525        title = _(u'Public Name'),
    532526        description = u"Substitute for officer's real name "
    533                        "in student object histories.",
     527                       "in object histories.",
    534528        required = False,)
    535529
     
    655649        )
    656650
    657     carry_over = schema.Bool(
    658         title = _(u'Carry-over Course Registration'),
    659         default = False,
    660         )
    661 
    662     current_academic_session = schema.Choice(
    663         title = _(u'Current Academic Session'),
    664         description = _(u'Session for which score editing is allowed'),
    665         source = academic_sessions_vocab,
    666         default = None,
    667         required = False,
    668         readonly = False,
    669         )
    670 
    671     next_matric_integer = schema.Int(
    672         title = _(u'Next Matriculation Number Integer'),
    673         description = _(u'Integer used for constructing the next '
    674                          'matriculation number'),
    675         default = 0,
    676         readonly = False,
    677         required = False,
    678         )
    679651
    680652class ISessionConfiguration(IKofaObject):
     
    682654    """
    683655
    684     academic_session = schema.Choice(
    685         title = _(u'Academic Session'),
    686         source = academic_sessions_vocab,
     656    application_session = schema.Choice(
     657        title = _(u'Period'),
     658        source = application_sessions_vocab,
    687659        default = None,
    688660        required = True,
     
    690662        )
    691663
    692     application_fee = schema.Float(
    693         title = _(u'Application Fee'),
    694         default = 0.0,
    695         required = False,
    696         )
    697 
    698     clearance_fee = schema.Float(
    699         title = _(u'Acceptance Fee'),
    700         default = 0.0,
    701         required = False,
    702         )
    703 
    704     booking_fee = schema.Float(
    705         title = _(u'Bed Booking Fee'),
    706         default = 0.0,
    707         required = False,
    708         )
    709 
    710     maint_fee = schema.Float(
    711         title = _(u'Rent (fallback)'),
    712         default = 0.0,
    713         required = False,
    714         )
    715 
    716     transcript_fee = schema.Float(
    717         title = _(u'Transcript Fee'),
    718         default = 0.0,
    719         required = False,
    720         )
    721 
    722     clearance_enabled = schema.Bool(
    723         title = _(u'Clearance enabled'),
    724         default = False,
    725         )
    726 
    727     payment_disabled = schema.List(
    728         title = _(u'Payment disabled'),
    729         value_type = schema.Choice(
    730             source = DisablePaymentGroupSource(),
    731             ),
    732         required = False,
    733         default = [],
    734         )
    735664
    736665    def getSessionString():
     
    743672    """
    744673
    745     academic_session = schema.Choice(
     674    application_session = schema.Choice(
    746675        title = _(u'Academic Session'),
    747         source = academic_sessions_vocab,
     676        source = application_sessions_vocab,
    748677        default = None,
    749678        required = True,
     
    751680        )
    752681
    753 ISessionConfigurationAdd['academic_session'].order =  ISessionConfiguration[
    754     'academic_session'].order
     682ISessionConfigurationAdd['application_session'].order =  ISessionConfiguration[
     683    'application_session'].order
    755684
    756685class IDataCenter(IKofaObject):
     
    873802    needing to know about that parts. The site simply collects all
    874803    available plugins, calls them and the plugins care for their
    875     respective subarea like the applicants area or the datacenter
     804    respective subarea like the cutomers area or the datacenter
    876805    area.
    877806
     
    11121041        interpret `attr` as a hint for what type of file for a given
    11131042        context should be stored if there are several types
    1114         possible. For instance for a certain student some file could
     1043        possible. For instance for a certain customer some file could
    11151044        be the connected passport photograph or some certificate scan
    11161045        or whatever. Each of them has to be stored in a different
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/mandates/container.py

    r8910 r11947  
    5656    def setup(self, site, name, logger):
    5757        if 'mandates' in site.keys():
    58             logger.warn('Could not create container for faculties in Kofa.')
     58            logger.warn('Could not create container for mandates in Kofa.')
    5959            return
    6060        site['mandates'] = MandatesContainer()
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/mandates/tests.py

    r11681 r11947  
    8585        shutil.rmtree(self.dc_root)
    8686
    87     def test_set_student_password(self):
     87    def xx_test_set_student_password(self):
    8888        student = createObject('waeup.Student')
    8989        # Add and execute a mandate with missing parameters.
     
    129129        self.assertTrue('system - PasswordMandate used: bob' in logcontent)
    130130
    131     def test_set_applicant_password(self):
    132         applicant = createObject('waeup.Applicant')
    133         applicant.applicant_id = u'abc'
    134         mandate = PasswordMandate()
    135         mandate.params['user'] = applicant
    136         mandate.params['password'] = 'mypwd1'
    137         self.app['mandates'].addMandate(mandate)
    138         msg = mandate.execute()
    139         # Password has been set.
    140         self.assertEqual(msg, 'Password has been successfully set. Login with your new password.')
    141         self.assertTrue(IUserAccount(applicant).checkPassword('mypwd1'))
    142         logfile = os.path.join(
    143             self.app['datacenter'].storage, 'logs', 'main.log')
    144         logcontent = open(logfile).read()
    145         self.assertTrue('system - PasswordMandate used: abc' in logcontent)
    146 
    147131    def test_remove_expired(self):
    148132        # mandate1 is an old mandate which just expired.
     
    159143        self.assertEqual([i for i in self.app['mandates'].keys()], [u'23456'])
    160144
    161     def test_browser(self):
     145    def xx_test_browser(self):
    162146        student = createObject('waeup.Student')
    163147        self.app['students'].addStudent(student)
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/payments/interfaces.py

    r11450 r11947  
    1919from zope import schema
    2020from waeup.kofa.interfaces import (
    21     IKofaObject, SimpleKofaVocabulary, academic_sessions_vocab,
     21    IKofaObject, SimpleKofaVocabulary, application_sessions_vocab,
    2222    ContextualDictSourceFactoryBase)
    2323from waeup.kofa.interfaces import MessageFactory as _
     
    6868    p_session = schema.Choice(
    6969        title = _(u'Payment Session'),
    70         source = academic_sessions_vocab,
     70        source = application_sessions_vocab,
    7171        required = True,
    7272        )
     
    133133    def approve():
    134134        "Approve an online payment and set to paid."
    135 
    136 class IPayer(IKofaObject):
    137     """An interface for an adapter to publish student and applicant data
    138     through a simple webservice.
    139 
    140     """
    141     display_fullname = Attribute('Name of  payer')
    142     id = Attribute('Id of payer')
    143     reg_number = Attribute('Reg number of payer')
    144     matric_number = Attribute('Matric number of payer')
    145     faculty = Attribute('Faculty of payer')
    146     department = Attribute('Department of payer')
    147     email= Attribute('Email of payer')
    148     phone= Attribute('Phone number of payer')
    149     current_mode= Attribute('Current study mode of payer')
    150     current_level= Attribute('Current level of payer')
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/permissions.py

    r11862 r11947  
    4444    grok.name('waeup.Authenticated')
    4545
    46 class ViewAcademicsPermission(grok.Permission):
    47     grok.name('waeup.viewAcademics')
    48 
    49 class ManageAcademicsPermission(grok.Permission):
    50     grok.name('waeup.manageAcademics')
     46class ViewProductsPermission(grok.Permission):
     47    grok.name('waeup.viewProducts')
     48
     49class ManageProductsPermission(grok.Permission):
     50    grok.name('waeup.manageProducts')
    5151
    5252class ManagePortal(grok.Permission):
     
    5656    grok.name('waeup.manageUsers')
    5757
    58 class ShowStudents(grok.Permission):
    59     grok.name('waeup.showStudents')
    60 
    61 class ClearAllStudents(grok.Permission):
    62     grok.name('waeup.clearAllStudents')
    63 
    64 class EditScores(grok.Permission):
    65     grok.name('waeup.editScores')
    66 
    6758class EditUser(grok.Permission):
    6859    grok.name('waeup.editUser')
     
    10495
    10596# Local Roles
    106 class ApplicationsManager(grok.Role):
    107     grok.name('waeup.local.ApplicationsManager')
    108     grok.title(u'Applications Manager')
    109     grok.permissions('waeup.viewAcademics')
    110 
    111 class DepartmentManager(grok.Role):
    112     grok.name('waeup.local.DepartmentManager')
    113     grok.title(u'Department Manager')
    114     grok.permissions('waeup.manageAcademics',
    115                      'waeup.showStudents',
    116                      'waeup.exportData')
    117 
    118 class DepartmentOfficer(grok.Role):
    119     grok.name('waeup.local.DepartmentOfficer')
    120     grok.title(u'Department Officer')
    121     grok.permissions('waeup.showStudents',
    122                      'waeup.viewAcademics',
    123                      'waeup.exportPaymentsOverview')
    124 
    125 class ClearanceOfficer(grok.Role):
    126     """The clearance officer role is meant for the
    127     assignment of dynamic roles only.
    128     """
    129     grok.name('waeup.local.ClearanceOfficer')
    130     grok.title(u'Clearance Officer')
    131     grok.permissions('waeup.showStudents',
    132                      'waeup.viewAcademics',
    133                      'waeup.exportData',
    134                      'waeup.clearAllStudents')
    135 
    136 class LocalStudentsManager(grok.Role):
    137     """The local students manager role is meant for the
    138     assignment of dynamic roles only.
    139     """
    140     grok.name('waeup.local.LocalStudentsManager')
    141     grok.title(u'Students Manager')
    142     grok.permissions('waeup.showStudents',
    143                      'waeup.viewAcademics',
    144                      'waeup.exportData')
    145 
    146 class LocalWorkflowManager(grok.Role):
    147     """The local workflow manager role is meant for the
    148     assignment of dynamic roles only.
    149     """
    150     grok.name('waeup.local.LocalWorkflowManager')
    151     grok.title(u'Student Workflow Manager')
    152     grok.permissions('waeup.showStudents',
    153                      'waeup.viewAcademics',
    154                      'waeup.exportData')
    155 
    156 class UGClearanceOfficer(grok.Role):
    157     """The clearance officer role is meant for the
    158     assignment of dynamic roles only.
    159     """
    160     grok.name('waeup.local.UGClearanceOfficer')
    161     grok.title(u'UG Clearance Officer')
    162     grok.permissions('waeup.showStudents',
    163                      'waeup.viewAcademics',
    164                      'waeup.exportData',
    165                      'waeup.clearAllStudents')
    166 
    167 class PGClearanceOfficer(grok.Role):
    168     """The clearance officer role is meant for the
    169     assignment of dynamic roles only.
    170     """
    171     grok.name('waeup.local.PGClearanceOfficer')
    172     grok.title(u'PG Clearance Officer')
    173     grok.permissions('waeup.showStudents',
    174                      'waeup.viewAcademics',
    175                      'waeup.exportData',
    176                      'waeup.clearAllStudents')
    177 
    178 class CourseAdviser100(grok.Role):
    179     """The 100 level course adviser role is meant for the
    180     assignment of dynamic roles only.
    181     """
    182     grok.name('waeup.local.CourseAdviser100')
    183     grok.title(u'Course Adviser 100L')
    184     grok.permissions('waeup.showStudents',
    185                      'waeup.viewAcademics',
    186                      'waeup.exportData')
    187 
    188 class CourseAdviser200(grok.Role):
    189     """The course 200 level adviser role is meant for the
    190     assignment of dynamic roles only.
    191     """
    192     grok.name('waeup.local.CourseAdviser200')
    193     grok.title(u'Course Adviser 200L')
    194     grok.permissions('waeup.showStudents',
    195                      'waeup.viewAcademics',
    196                      'waeup.exportData')
    197 
    198 class CourseAdviser300(grok.Role):
    199     """The 300 level course adviser role is meant for the
    200     assignment of dynamic roles only.
    201     """
    202     grok.name('waeup.local.CourseAdviser300')
    203     grok.title(u'Course Adviser 300L')
    204     grok.permissions('waeup.showStudents',
    205                      'waeup.viewAcademics',
    206                      'waeup.exportData')
    207 
    208 class CourseAdviser400(grok.Role):
    209     """The 400 level course adviser role is meant for the
    210     assignment of dynamic roles only.
    211     """
    212     grok.name('waeup.local.CourseAdviser400')
    213     grok.title(u'Course Adviser 400L')
    214     grok.permissions('waeup.showStudents',
    215                      'waeup.viewAcademics',
    216                      'waeup.exportData')
    217 
    218 class CourseAdviser500(grok.Role):
    219     """The 500 level course adviser role is meant for the
    220     assignment of dynamic roles only.
    221     """
    222     grok.name('waeup.local.CourseAdviser500')
    223     grok.title(u'Course Adviser 500L')
    224     grok.permissions('waeup.showStudents',
    225                      'waeup.viewAcademics',
    226                      'waeup.exportData')
    227 
    228 class CourseAdviser600(grok.Role):
    229     """The 600 level course adviser role is meant for the
    230     assignment of dynamic roles only.
    231     """
    232     grok.name('waeup.local.CourseAdviser600')
    233     grok.title(u'Course Adviser 600L')
    234     grok.permissions('waeup.showStudents',
    235                      'waeup.viewAcademics',
    236                      'waeup.exportData')
    237 
    238 class CourseAdviser700(grok.Role):
    239     """The 700 level course adviser role is meant for the
    240     assignment of dynamic roles only.
    241     """
    242     grok.name('waeup.local.CourseAdviser700')
    243     grok.title(u'Course Adviser 700L')
    244     grok.permissions('waeup.showStudents',
    245                      'waeup.viewAcademics',
    246                      'waeup.exportData')
    247 
    248 class CourseAdviser800(grok.Role):
    249     """The 800 level course adviser role is meant for the
    250     assignment of dynamic roles only.
    251     """
    252     grok.name('waeup.local.CourseAdviser800')
    253     grok.title(u'Course Adviser 800L')
    254     grok.permissions('waeup.showStudents',
    255                      'waeup.viewAcademics',
    256                      'waeup.exportData')
    257 
    258 class Lecturer(grok.Role):
    259     """The lecturer role is meant for the
    260     assignment of dynamic roles only.
    261     """
    262     grok.name('waeup.local.Lecturer')
    263     grok.title(u'Lecturer')
    264     grok.permissions('waeup.showStudents',
    265                      'waeup.editScores',
    266                      'waeup.viewAcademics',
    267                      'waeup.exportData')
    26897
    26998class Owner(grok.Role):
     
    273102
    274103# Site Roles
    275 class AcademicsOfficer(grok.Role):
    276     grok.name('waeup.AcademicsOfficer')
    277     grok.title(u'Academics Officer (view only)')
    278     grok.permissions('waeup.viewAcademics')
    279 
    280 class AcademicsManager(grok.Role):
    281     grok.name('waeup.AcademicsManager')
    282     grok.title(u'Academics Manager')
    283     grok.permissions('waeup.viewAcademics',
    284                      'waeup.manageAcademics')
    285 
    286 class ACManager(grok.Role):
    287     grok.name('waeup.ACManager')
    288     grok.title(u'Access Code Manager')
    289     grok.permissions('waeup.manageACBatches')
     104class ProductsOfficer(grok.Role):
     105    grok.name('waeup.ProductsOfficer')
     106    grok.title(u'Products Officer (view only)')
     107    grok.permissions('waeup.viewProducts')
     108
     109class ProductssManager(grok.Role):
     110    grok.name('waeup.ProductsManager')
     111    grok.title(u'Products Manager')
     112    grok.permissions('waeup.viewProducts',
     113                     'waeup.manageProducts')
    290114
    291115class DataCenterManager(grok.Role):
     
    306130                     'waeup.exportData')
    307131
    308 class BursaryOfficer(grok.Role):
    309     grok.name('waeup.BursaryOfficer')
    310     grok.title(u'Bursary Officer')
    311     grok.permissions('waeup.showStudents',
    312                      'waeup.viewAcademics',
    313                      'waeup.exportBursaryData')
    314 
    315132class UsersManager(grok.Role):
    316133    grok.name('waeup.UsersManager')
     
    329146    grok.permissions('waeup.managePortal',
    330147                     'waeup.manageUsers',
    331                      'waeup.viewAcademics', 'waeup.manageAcademics',
     148                     'waeup.viewProducts', 'waeup.manageProducts',
    332149                     'waeup.manageACBatches',
    333150                     'waeup.manageDataCenter',
     
    335152                     'waeup.exportData',
    336153                     'waeup.viewTranscript',
    337                      'waeup.managePortalConfiguration', 'waeup.viewApplication',
    338                      'waeup.manageApplication', 'waeup.handleApplication',
    339                      'waeup.viewApplicantsTab', 'waeup.payApplicant',
    340                      'waeup.viewApplicationStatistics',
    341                      'waeup.viewStudent', 'waeup.manageStudent',
    342                      'waeup.clearStudent', 'waeup.payStudent',
    343                      'waeup.uploadStudentFile', 'waeup.showStudents',
    344                      'waeup.clearAllStudents',
    345                      'waeup.editScores',
    346                      'waeup.triggerTransition',
    347                      'waeup.viewStudentsContainer','waeup.viewStudentsTab',
    348                      'waeup.handleAccommodation',
    349                      'waeup.viewHostels', 'waeup.manageHostels',
     154                     'waeup.managePortalConfiguration',
    350155                     'waeup.editUser',
    351                      'waeup.loginAsStudent',
    352156                     'waeup.manageReports',
    353157                     'waeup.manageJobs',
     
    363167    grok.permissions(#'waeup.managePortal',
    364168                     #'waeup.manageUsers',
    365                      'waeup.viewAcademics', 'waeup.manageAcademics',
     169                     'waeup.viewProducts', 'waeup.manageProducts',
    366170                     #'waeup.manageACBatches',
    367171                     'waeup.manageDataCenter',
     
    369173                     'waeup.exportData',
    370174                     'waeup.viewTranscript',
    371                      'waeup.managePortalConfiguration', 'waeup.viewApplication',
    372                      'waeup.manageApplication', 'waeup.handleApplication',
    373                      'waeup.viewApplicantsTab', 'waeup.payApplicant',
    374                      'waeup.viewApplicationStatistics',
    375                      'waeup.viewStudent', 'waeup.manageStudent',
    376                      'waeup.clearStudent', 'waeup.payStudent',
    377                      'waeup.uploadStudentFile', 'waeup.showStudents',
    378                      'waeup.clearAllStudents',
    379                      'waeup.editScores',
    380                      #'waeup.triggerTransition',
    381                      'waeup.viewStudentsContainer','waeup.viewStudentsTab',
    382                      'waeup.handleAccommodation',
    383                      'waeup.viewHostels', 'waeup.manageHostels',
     175                     'waeup.managePortalConfiguration',
    384176                     #'waeup.editUser',
    385                      #'waeup.loginAsStudent',
    386177                     'waeup.manageReports',
    387178                     #'waeup.manageJobs',
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/permissions.txt

    r10639 r11947  
    2929
    3030    >>> sorted(list(get_all_roles()))
    31     [(u'waeup.ACManager', <waeup.kofa.permissions.ACManager object at 0x...]
     31    [(u'waeup.DataCenterManager', <waeup.kofa.permissions.DataCenterManager object at 0x...]
    3232
    3333:func:`get_waeup_roles`
     
    3939    >>> from waeup.kofa.permissions import get_waeup_roles
    4040    >>> len(list(get_waeup_roles()))
    41     22
     41    9
    4242
    4343    >>> len(list(get_waeup_roles(also_local=True)))
    44     42
     44    10
    4545
    4646
     
    5353    >>> from waeup.kofa.permissions import get_waeup_role_names
    5454    >>> list(get_waeup_role_names())
    55     [u'waeup.ACManager',
    56      u'waeup.AcademicsManager',
    57      u'waeup.AcademicsOfficer',
    58      u'waeup.AccommodationOfficer',
    59      u'waeup.Applicant',
    60      u'waeup.ApplicationsManager',
    61      u'waeup.ApplicationsOfficer',
    62      u'waeup.BursaryOfficer',
    63      u'waeup.DataCenterManager',
    64      u'waeup.ExportManager',
    65      u'waeup.ImportManager',
    66      u'waeup.PortalManager',
    67      u'waeup.Student',
    68      u'waeup.StudentImpersonator',
    69      u'waeup.StudentsClearanceOfficer',
    70      u'waeup.StudentsCourseAdviser',
    71      u'waeup.StudentsManager',
    72      u'waeup.StudentsOfficer',
    73      u'waeup.TranscriptOfficer',
    74      u'waeup.UsersManager',
    75      u'waeup.WorkflowManager',
    76      u'waeup.xmlrpcusers1']
     55    [u'waeup.DataCenterManager',
     56    u'waeup.ExportManager',
     57    u'waeup.ImportManager',
     58    u'waeup.PortalManager',
     59    u'waeup.ProductsManager',
     60    u'waeup.ProductsOfficer',
     61    u'waeup.UsersManager',
     62    u'waeup.WorkflowManager',
     63    u'waeup.xmlrpcusers1']
    7764
    7865:func:`get_users_with_local_roles`
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/tests/test_app.py

    r9217 r11947  
    5757        return
    5858
    59     def test_update_plugins(self):
    60         # We can update plugins
    61         setSite(self.app)
    62         del self.app['accesscodes']
    63         self.app.updatePlugins()
    64         self.assertTrue('accesscodes' in self.app.keys())
    65         return
    66 
    6759    def test_jobs(self):
    6860        # We can get the global job manager when traversing to it...
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/utils/batching.py

    r11849 r11947  
    338338                obj = self.callFactory()
    339339                # Override all values in row, also
    340                 # student_ids and applicant_ids which have been
     340                # customer ids which have been
    341341                # generated in the respective __init__ methods before.
    342342                self.updateEntry(obj, row, site, base)
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/utils/browser.py

    r9127 r11947  
    2626
    2727from waeup.kofa.interfaces import IUniversity
    28 
    29 def replaceStudentMessages(old, new):
    30     students = grok.getSite()['students']
    31     for student in students.values():
    32         history = IObjectHistory(student)
    33         history.modifyMessages(old, new)
    34     return
    35 
    36 def replaceApplicantMessages(old, new):
    37     applicants = grok.getSite()['applicants']
    38     for container in applicants.values():
    39         for applicant in container.values():
    40             history = IObjectHistory(applicant)
    41             history.modifyMessages(old, new)
    42     return
    43 
    44 def removeStudentMessage(student_id, number):
    45     students = grok.getSite()['students']
    46     student = students.get(student_id, None)
    47     if student:
    48         history = IObjectHistory(student)
    49         success, text = history.removeMessage(number)
    50     return success, text
    51 
    52 def removeApplicantMessage(applicant_id, number):
    53     applicants = grok.getSite()['applicants']
    54     try:
    55         container, application_number = applicant_id.split('_')
    56     except:
    57         return False, 'applicant_id is wrong'
    58     container = applicants.get(container, None)
    59     if not container:
    60         return False, 'No such container'
    61     applicant = container.get(application_number, None)
    62     if applicant is None:
    63         return False, 'No such applicant'
    64     history = IObjectHistory(applicant)
    65     success, text = history.removeMessage(number)
    66     return success, text
    6728
    6829class ReindexPage(UtilityView, grok.View):
     
    9556        self.redirect(self.url(self.context, '@@index'))
    9657        return
    97 
    98 class ModifyAllStudentHistory(UtilityView, grok.View):
    99     """ View to modify all student histories.
    100 
    101     """
    102     grok.context(IUniversity)
    103     grok.name('modify_student_history')
    104     grok.require('waeup.managePortal')
    105 
    106     def update(self,old=None, new=None):
    107         if None in (old, new):
    108             self.flash('Syntax: /modify_student_history?old=[old string]&new=[new string]')
    109             return
    110         replaceStudentMessages(old, new)
    111         self.context.logger.info(
    112             "'%s' replaced by '%s' in all student histories." % (old, new))
    113         self.flash('Finished')
    114         return
    115 
    116     def render(self):
    117         self.redirect(self.url(self.context, '@@index'))
    118         return
    119 
    120 class RemoveStudentHistoryMessage(UtilityView, grok.View):
    121     """ View to remove a single student history entry.
    122 
    123     """
    124     grok.context(IUniversity)
    125     grok.name('remove_student_history_message')
    126     grok.require('waeup.managePortal')
    127 
    128     def update(self,student_id=None, number=None):
    129         if None in (student_id, number):
    130             self.flash('Syntax: /remove_student_history_message?student_id=[id]&number=[line number, starting with 0]')
    131             return
    132         try:
    133             number=int(number)
    134         except:
    135             self.flash('Error')
    136             return
    137         success, text = removeStudentMessage(student_id, number)
    138         if not success:
    139             self.flash('Error: %s' % text)
    140             return
    141         self.context.logger.info(
    142             "line '%s' removed in %s history" % (text, student_id))
    143         self.flash('Finished')
    144         return
    145 
    146     def render(self):
    147         self.redirect(self.url(self.context, '@@index'))
    148         return
    149 
    150 class ModifyAllApplicantHistory(UtilityView, grok.View):
    151     """ View to modify all student histories.
    152 
    153     """
    154     grok.context(IUniversity)
    155     grok.name('modify_applicant_history')
    156     grok.require('waeup.managePortal')
    157 
    158     def update(self,old=None, new=None):
    159         if None in (old, new):
    160             self.flash('Syntax: /modify_applicant_history?old=[old string]&new=[new string]')
    161             return
    162         replaceApplicantMessages(old, new)
    163         self.context.logger.info(
    164             "'%s' replaced by '%s' in all applicant histories." % (old, new))
    165         self.flash('Finished')
    166         return
    167 
    168     def render(self):
    169         self.redirect(self.url(self.context, '@@index'))
    170         return
    171 
    172 class RemoveApplicantHistoryMessage(UtilityView, grok.View):
    173     """ View to remove a single applicant history entry.
    174 
    175     """
    176     grok.context(IUniversity)
    177     grok.name('remove_applicant_history_message')
    178     grok.require('waeup.managePortal')
    179 
    180     def update(self,applicant_id=None, number=None):
    181         if None in (applicant_id, number):
    182             self.flash('Syntax: /remove_applicant_history_message?applicant_id=[id]&number=[line number, starting with 0]')
    183             return
    184         try:
    185             number=int(number)
    186         except:
    187             self.flash('Error')
    188             return
    189         success, text = removeApplicantMessage(applicant_id, number)
    190         if not success:
    191             self.flash('Error: %s' % text)
    192             return
    193         self.context.logger.info(
    194             "line '%s' removed in %s history" % (text, applicant_id))
    195         self.flash('Finished')
    196         return
    197 
    198     def render(self):
    199         self.redirect(self.url(self.context, '@@index'))
    200         return
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/utils/helpers.py

    r11824 r11947  
    235235    grok.name(u'waeup.Factory')
    236236    title = u"Create instances of ``factory``.",
    237     description = u"This factory instantiates new applicant instances."
     237    description = u"This factory instantiates new e.g. applicant instances."
    238238    factory = None
    239239
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/utils/tests/test_converters.py

    r8216 r11947  
    3838    DELETION_MARKER, IGNORE_MARKER)
    3939from waeup.kofa.schoolgrades import ResultEntryField
    40 from waeup.kofa.university import Faculty
    4140from waeup.kofa.utils.converters import (
    4241    IObjectConverter, IFieldConverter, DefaultFieldConverter,
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/utils/utils.py

    r11821 r11947  
    258258        """Send credentials as email.
    259259
    260         Input is the applicant for which credentials are sent and the
     260        Input is the customer for which credentials are sent and the
    261261        password.
    262262
  • main/waeup.kofa/branches/henrik-regista/src/waeup/kofa/webservices.py

    r10477 r11947  
    2020from zope.component import getUtility
    2121from zope.catalog.interfaces import ICatalog
    22 from waeup.kofa.payments.interfaces import IPayer
    23 from waeup.kofa.interfaces import IUniversity, academic_sessions_vocab
    24 
    25 class PaymentDataWebservice(grok.View):
    26     """A simple webservice to publish payment and payer details on request from
    27     accepted IP addresses without authentication.
    28 
    29     """
    30     grok.context(IUniversity)
    31     grok.name('paymentrequest')
    32     grok.require('waeup.Public')
    33 
    34     #ACCEPTED_IP = ('174.36.230.28', )
    35     ACCEPTED_IP = ('127.0.0.1', )
    36 
    37     def update(self, P_ID=None):
    38         if P_ID == None:
    39             self.output = '-1'
    40             return
    41         real_ip = self.request.get('HTTP_X_FORWARDED_FOR', None)
    42         if real_ip:
    43             self.context.logger.info('PaymentDataWebservice called: %s' % real_ip)
    44         if real_ip and self.ACCEPTED_IP:
    45             if real_ip not in  self.ACCEPTED_IP:
    46                 self.output = '-4'
    47                 return
    48         cat = getUtility(ICatalog, name='payments_catalog')
    49         results = list(
    50             cat.searchResults(p_id=(P_ID, P_ID), p_state=('paid', 'paid')))
    51         if len(results) != 1:
    52             self.output = '-1'
    53             return
    54         try:
    55             owner = IPayer(results[0])
    56             full_name = owner.display_fullname
    57             reg_number = owner.reg_number
    58             matric_number = owner.matric_number
    59             faculty = owner.faculty
    60             department = owner.department
    61         except (TypeError, AttributeError):
    62             self.output = '-3'
    63             return
    64         amount = results[0].amount_auth
    65         payment_category = results[0].category
    66         payment_item = results[0].p_item
    67         academic_session = academic_sessions_vocab.getTerm(
    68             results[0].p_session).title
    69         self.output = (
    70             'FULL_NAME=%s&' +
    71             'FACULTY=%s&' +
    72             'DEPARTMENT=%s&' +
    73             'PAYMENT_ITEM=%s&' +
    74             'PAYMENT_CATEGORY=%s&' +
    75             'ACADEMIC_SESSION=%s&' +
    76             'MATRIC_NUMBER=%s&' +
    77             'REG_NUMBER=%s&' +
    78             'FEE_AMOUNT=%s') % (full_name, faculty,
    79             department, payment_item, payment_category,
    80             academic_session, matric_number, reg_number, amount)
    81         return
    82 
    83     def render(self):
    84         return self.output
     22from waeup.kofa.interfaces import IUniversity, application_sessions_vocab
    8523
    8624class XMLRPCPermission(grok.Permission):
Note: See TracChangeset for help on using the changeset viewer.