Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 8471)
@@ -1686,22 +1686,18 @@
         return
 
-class StartCourseRegistrationPage(KofaPage):
+class StartSessionPage(KofaPage):
     grok.context(IStudentStudyCourse)
-    grok.name('start_course_registration')
+    grok.name('start_session')
     grok.require('waeup.handleStudent')
     grok.template('enterpin')
-    label = _('Start course registration')
+    label = _('Start session')
     ac_prefix = 'SFE'
     notice = ''
     pnav = 4
-    buttonname = _('Start course registration now')
+    buttonname = _('Start now')
 
     def update(self, SUBMIT=None):
-        if not self.context.getStudent().state in (CLEARED,RETURNING):
-            self.flash(_("You are in wrong state."))
-            self.redirect(self.url(self.context))
-            return
-        if not self.context.may_register:
-            self.flash(_("You are not entitled to start course registration."))
+        if not self.context.next_session_allowed:
+            self.flash(_("You are not entitled to start session."))
             self.redirect(self.url(self.context))
             return
@@ -1717,5 +1713,4 @@
             return
         # Mark pin as used (this also fires a pin related transition)
-        # and fire transition start_clearance
         if code.state == USED:
             self.flash(_('Activation code has already been used.'))
@@ -1724,5 +1719,5 @@
             comment = _(u"invalidated")
             # Here we know that the ac is in state initialized so we do not
-            # expect an exception, but the owner might be different
+            # expect an error, but the owner might be different
             if not invalidate_accesscode(
                 pin,comment,self.context.getStudent().student_id):
@@ -1735,5 +1730,8 @@
             IWorkflowInfo(self.context.getStudent()).fireTransition(
                 'pay_school_fee')
-        self.flash(_('Course registration has been started.'))
+        elif self.context.getStudent().state == PAID:
+            IWorkflowInfo(self.context.getStudent()).fireTransition(
+                'pay_pg_fee')
+        self.flash(_('Session started.'))
         self.redirect(self.url(self.context))
         return
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/studycourse.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/studycourse.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/studycourse.py	(revision 8471)
@@ -27,4 +27,5 @@
     IStudentStudyCourse, IStudentNavigation, IStudentStudyLevel)
 from waeup.kofa.students.studylevel import CourseTicket
+from waeup.kofa.students.workflow import CLEARED, RETURNING, PAID
 from waeup.kofa.utils.helpers import attrs_to_fields
 
@@ -43,6 +44,11 @@
 
     @property
-    def may_register(self):
-        return True
+    def next_session_allowed(self):
+        if self.getStudent().state in (CLEARED, RETURNING):
+            return True
+        if self.getStudent().state == PAID \
+            and self.getStudent().current_mode.startswith('pg'):
+            return True
+        return False
 
     def addStudentStudyLevel(self, cert, studylevel):
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 8471)
@@ -1483,7 +1483,7 @@
         self.assertTrue('Successfully removed' in self.browser.contents)
 
-        # The new SFE-0 pin can be used for starting course registration
+        # The new SFE-0 pin can be used for starting new session
         self.browser.open(self.studycourse_path)
-        self.browser.getLink('Start course registration').click()
+        self.browser.getLink('Start session').click()
         pin = self.app['accesscodes']['SFE-0'].keys()[0]
         parts = pin.split('-')[1:]
@@ -1491,8 +1491,97 @@
         self.browser.getControl(name="ac_series").value = sfeseries
         self.browser.getControl(name="ac_number").value = sfenumber
-        self.browser.getControl("Start course registration now").click()
-        self.assertMatches('...Course registration has been started...',
+        self.browser.getControl("Start now").click()
+        self.assertMatches('...Session started...',
                            self.browser.contents)
         self.assertTrue(self.student.state == 'school fee paid')
+        return
+
+    def test_postgraduate_payments(self):
+        self.certificate.study_mode = 'pg_ft'
+        self.certificate.start_level = 999
+        self.certificate.end_level = 999
+        self.student['studycourse'].current_level = 999
+        # Login
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.student_id
+        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl("Login").click()
+        # Students can add online school fee payment tickets.
+        IWorkflowState(self.student).setState('cleared')
+        self.browser.open(self.payments_path)
+        self.browser.getControl("Add online payment ticket").click()
+        self.browser.getControl(name="form.p_category").value = ['schoolfee']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[0]
+        self.browser.getLink(value).click()
+        self.assertMatches('...Amount Authorized...',
+                           self.browser.contents)
+        # Payment session and level are current ones.
+        # Postgrads have to school_fee_1.
+        self.assertEqual(self.student['payments'][value].amount_auth, 40000.0)
+        self.assertEqual(self.student['payments'][value].p_session, 2004)
+        self.assertEqual(self.student['payments'][value].p_level, 999)
+
+        # We simulate the approval
+        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
+        self.browser.open(self.browser.url + '/fake_approve')
+        self.assertMatches('...Successful payment...',
+                          self.browser.contents)
+
+        # The new SFE-0 pin can be used for starting session
+        self.browser.open(self.studycourse_path)
+        self.browser.getLink('Start session').click()
+        pin = self.app['accesscodes']['SFE-0'].keys()[0]
+        parts = pin.split('-')[1:]
+        sfeseries, sfenumber = parts
+        self.browser.getControl(name="ac_series").value = sfeseries
+        self.browser.getControl(name="ac_number").value = sfenumber
+        self.browser.getControl("Start now").click()
+        self.assertMatches('...Session started...',
+                           self.browser.contents)
+        self.assertTrue(self.student.state == 'school fee paid')
+
+        # Postgrad students do not need to register courses the
+        # can just pay for the next session.
+        self.browser.open(self.payments_path)
+        # Remove first payment to be sure that we access the right ticket
+        del self.student['payments'][value]
+        self.browser.getControl("Add online payment ticket").click()
+        self.browser.getControl(name="form.p_category").value = ['schoolfee']
+        self.browser.getControl("Create ticket").click()
+        ctrl = self.browser.getControl(name='val_id')
+        value = ctrl.options[0]
+        self.browser.getLink(value).click()
+        # Payment session has increased by one, payment level remains the same.
+        # Returning Postgraduates have to pay school_fee_2.
+        self.assertEqual(self.student['payments'][value].amount_auth, 20000.0)
+        self.assertEqual(self.student['payments'][value].p_session, 2005)
+        self.assertEqual(self.student['payments'][value].p_level, 999)
+
+        # Student is still in old session
+        self.assertEqual(self.student.current_session, 2004)
+
+        # We do not need to pay the ticket if any other
+        # SFE pin is provided
+        pin_container = self.app['accesscodes']
+        pin_container.createBatch(
+            datetime.utcnow(), 'some_userid', 'SFE', 9.99, 1)
+        pin = pin_container['SFE-1'].values()[0].representation
+        sfeseries, sfenumber = pin.split('-')[1:]
+        # The new SFE-1 pin can be used for starting new session
+        self.browser.open(self.studycourse_path)
+        self.browser.getLink('Start session').click()
+        self.browser.getControl(name="ac_series").value = sfeseries
+        self.browser.getControl(name="ac_number").value = sfenumber
+        self.browser.getControl("Start now").click()
+        self.assertMatches('...Session started...',
+                           self.browser.contents)
+        self.assertTrue(self.student.state == 'school fee paid')
+        # Student is in new session
+        self.assertEqual(self.student.current_session, 2005)
+        self.assertEqual(self.student['studycourse'].current_level, 999)
         return
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 8471)
@@ -36,5 +36,5 @@
 from zope.formlib.form import setUpEditWidgets
 
-from waeup.kofa.interfaces import IExtFileStore, IKofaUtils, RETURNING
+from waeup.kofa.interfaces import IExtFileStore, IKofaUtils, RETURNING, PAID
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.students.interfaces import IStudentsUtils
@@ -278,4 +278,10 @@
                 details['p_session'], details[
                     'p_level'] = self.getReturningData(student)
+            elif student.current_mode.startswith('pg') and student.state == PAID:
+                # Returning postgraduate students also pay for the next session
+                # but their level always remains the same.
+                details['p_session'] += 1
+                details['amount'] = getattr(
+                    student['studycourse'].certificate,'school_fee_2')
         elif category == 'clearance':
             details['p_item'] = student['studycourse'].certificate.code
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 8471)
@@ -431,5 +431,5 @@
         return self.view.url(self.view.context, self.target)
 
-class CourseRegistrationStartActionButton(ManageActionButton):
+class SartSessionActionButton(ManageActionButton):
     grok.order(1)
     grok.context(IStudentStudyCourse)
@@ -437,13 +437,12 @@
     grok.require('waeup.handleStudent')
     icon = 'actionicon_start.gif'
-    text = _('Start course registration')
-    target = 'start_course_registration'
-
-    @property
-    def target_url(self):
-        if not self.context.getStudent().state in (CLEARED,RETURNING) \
-            or not self.context.may_register:
-            return ''
-        return self.view.url(self.view.context, self.target)
+    text = _('Start session')
+    target = 'start_session'
+
+    @property
+    def target_url(self):
+        if self.context.next_session_allowed:
+            return self.view.url(self.view.context, self.target)
+        return False
 
 class AddStudyLevelActionButton(AddActionButton):
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/vocabularies.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/vocabularies.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/vocabularies.py	(revision 8471)
@@ -40,5 +40,7 @@
         start_level = int(studycourse.certificate.start_level)
         end_level = int(studycourse.certificate.end_level)
-        if start_level == 10:
+        if start_level == 999 or end_level == 999:
+            levels = [999]
+        elif start_level == 10:
             levels = [10,] + [level for level in range(100,end_level+200,10)
                 if level % 100 < 30]
@@ -73,4 +75,9 @@
             start_level = 100
             end_level = 1000
+        if start_level == 999 or end_level == 999:
+            if value != 999:
+                return _('Error: wrong level id ${value}',
+                    mapping={'value': value})
+            return course_levels.by_value[999].title
         if value < start_level or value > end_level + 120:
             return _('Error: level id ${value} out of range',
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/workflow.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/workflow.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/workflow.py	(revision 8471)
@@ -106,6 +106,13 @@
         transition_id = 'pay_school_fee',
         title = _('Pay school fee'),
-        msg = _('School fee paid'),
+        msg = _('Payment made'),
         source = RETURNING,
+        destination = PAID),
+
+    Transition(
+        transition_id = 'pay_pg_fee',
+        title = _('Pay postgraduate school fee'),
+        msg = _('Payment made'),
+        source = PAID,
         destination = PAID),
 
@@ -115,4 +122,11 @@
         msg = _('School fee payment approved'),
         source = RETURNING,
+        destination = PAID),
+
+    Transition(
+        transition_id = 'approve_pg_fee',
+        title = _('Approve postgraduate payment'),
+        msg = _('School fee payment approved'),
+        source = PAID,
         destination = PAID),
 
@@ -198,4 +212,5 @@
 
     Lock and unlock clearance form.
+    Triger actions after school fee payment.
     """
 
@@ -212,4 +227,8 @@
         'pay_school_fee', 'approve_school_fee'):
         getUtility(IStudentsUtils).setReturningData(obj)
+    elif event.transition.transition_id in (
+        'pay_pg_fee', 'approve_pg_fee'):
+        new_session = obj['studycourse'].current_session + 1
+        obj['studycourse'].current_session = new_session
     # In some tests we don't have a students container
     try:
Index: main/waeup.kofa/trunk/src/waeup/kofa/university/vocabularies.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/university/vocabularies.py	(revision 8468)
+++ main/waeup.kofa/trunk/src/waeup/kofa/university/vocabularies.py	(revision 8471)
@@ -37,4 +37,5 @@
     (_('800 (Year 8)'),800),
     (_('900 (Year 9)'),900),
+    (_('Postgraduate Level'),999),
     )
 
