Index: main/waeup.aaue/trunk/src/waeup/aaue/interfaces.py
===================================================================
--- main/waeup.aaue/trunk/src/waeup/aaue/interfaces.py	(revision 8746)
+++ main/waeup.aaue/trunk/src/waeup/aaue/interfaces.py	(revision 8753)
@@ -97,5 +97,5 @@
 
     school_fee_base = schema.Float(
-        title = _(u'School Fee (ignored)'),
+        title = _(u'School Fee Instalments'),
         default = 0.0,
         required = False,
Index: main/waeup.aaue/trunk/src/waeup/aaue/payments/interfaces.py
===================================================================
--- main/waeup.aaue/trunk/src/waeup/aaue/payments/interfaces.py	(revision 8746)
+++ main/waeup.aaue/trunk/src/waeup/aaue/payments/interfaces.py	(revision 8753)
@@ -19,5 +19,17 @@
 from zope import schema
 from waeup.kofa.payments.interfaces import IPayment
+from waeup.kofa.interfaces import SimpleKofaVocabulary
 from waeup.kofa.interfaces import MessageFactory as _
+
+payment_categories = SimpleKofaVocabulary(
+    (_('School Fee 1st instalment'),'schoolfee_1'),
+    (_('School Fee 2nd instalment'),'schoolfee_2'),
+    (_('Clearance'),'clearance'),
+    (_('Bed Allocation'),'bed_allocation'),
+    (_('Hostel Maintenance'),'hostel_maintenance'),
+    (_('Transfer'),'transfer'),
+    (_('Gown'),'gown'),
+    (_('Application Fee'), 'application'),
+    )
 
 class ICustomOnlinePayment(IPayment):
@@ -25,4 +37,11 @@
 
     """
+
+    p_category = schema.Choice(
+        title = _(u'Payment Category'),
+        default = u'schoolfee_1',
+        vocabulary = payment_categories,
+        required = True,
+        )
 
     ac = schema.TextLine(
@@ -76,2 +95,5 @@
         readonly = False,
         )
+
+ICustomOnlinePayment['p_category'].order = ICustomOnlinePayment[
+    'p_category'].order
Index: main/waeup.aaue/trunk/src/waeup/aaue/students/payments.py
===================================================================
--- main/waeup.aaue/trunk/src/waeup/aaue/students/payments.py	(revision 8746)
+++ main/waeup.aaue/trunk/src/waeup/aaue/students/payments.py	(revision 8753)
@@ -27,4 +27,5 @@
 from waeup.kofa.utils.helpers import attrs_to_fields
 from waeup.aaue.students.interfaces import ICustomStudentOnlinePayment
+from waeup.aaue.payments.interfaces import payment_categories
 
 class CustomStudentOnlinePayment(StudentOnlinePayment):
@@ -47,4 +48,8 @@
         return self.__parent__.__parent__
 
+    @property
+    def category(self):
+        return payment_categories.getTermByToken(self.p_category).title
+
 CustomStudentOnlinePayment = attrs_to_fields(CustomStudentOnlinePayment)
 
Index: main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py
===================================================================
--- main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py	(revision 8746)
+++ main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py	(revision 8753)
@@ -194,8 +194,15 @@
         self.browser.getControl("Add online payment ticket").click()
         self.browser.getControl("Create ticket").click()
+        self.assertMatches('...Wrong state...',
+                           self.browser.contents)
+        IWorkflowState(self.student).setState('cleared')
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl("Create ticket").click()
         self.assertMatches('...Amount could not be determined...',
                            self.browser.contents)
-        IWorkflowState(self.student).setState('cleared')
-        self.browser.open(self.payments_path + '/addop')
+
+        self.app['configuration']['2004'].school_fee_base = 6666.0
+
+        self.browser.getControl("Add online payment ticket").click()
         self.browser.getControl("Create ticket").click()
         self.assertMatches('...ticket created...',
@@ -217,4 +224,32 @@
         self.assertMatches('...This type of payment has already been made...',
                            self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        # Also the other payments can be made
+        self.browser.getControl(name="form.p_category").value = ['gown']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['transfer']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(
+            name="form.p_category").value = ['bed_allocation']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(
+            name="form.p_category").value = ['hostel_maintenance']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['clearance']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
         # Remove all payments so that we can add a school fee payment again
         keys = [i for i in self.student['payments'].keys()]
@@ -222,53 +257,41 @@
             del self.student['payments'][payment]
         self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['gown']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['transfer']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['bed_allocation']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(
-            name="form.p_category").value = ['hostel_maintenance']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['clearance']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['schoolfee']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        # In state returning we can add a new school fee ticket since
-        # p_session and p_level is different
+        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        # In state returning we can't add a new school fee ticket 
+        # for the next session because the second instalment is missing ...
         IWorkflowState(self.student).setState('returning')
         self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['schoolfee']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...ticket created...',
-                           self.browser.contents)
-        # In state admitted school fee can't be determined
-        IWorkflowState(self.student).setState('admitted')
-        self.browser.open(self.payments_path + '/addop')
-        self.browser.getControl(name="form.p_category").value = ['schoolfee']
-        self.browser.getControl("Create ticket").click()
-        self.assertMatches('...Amount could not be determined...',
+        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...2nd school fee instalment has not yet been paid...',
+                           self.browser.contents)
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
+        # ... and the first one has not yet been approved.
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...1st school fee instalment has not yet been paid...',
+                           self.browser.contents)
+        # Ok, then we approve the first instalment ...
+        ctrl = self.browser.getControl(name='val_id')
+        p_id = ctrl.options[0]
+        self.browser.open(self.payments_path + '/' + p_id + '/approve')
+        # ... add the second instalment ...
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        # ... approve the second instalment ...
+        ctrl = self.browser.getControl(name='val_id')
+        p_id = ctrl.options[1]
+        self.browser.open(self.payments_path + '/' + p_id + '/approve')
+        # ... and finally add the 1st instalment for the next session.
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
                            self.browser.contents)
 
@@ -324,15 +347,17 @@
         self.app['configuration']['2004'].booking_fee = 150.0
         self.app['configuration']['2004'].maint_fee = 180.0
+        self.app['configuration']['2004'].clearance_fee = 1234.0
+        self.app['configuration']['2004'].school_fee_base = 6666.0
         utils = getUtility(IStudentsUtils)
 
-        error, payment = utils.setPaymentDetails('schoolfee',self.student)
+        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
         self.assertEqual(payment, None)
-        self.assertEqual(error, u'Amount could not be determined.')
+        self.assertEqual(error, u'Wrong state.')
 
         IWorkflowState(self.student).setState('cleared')
-        error, payment = utils.setPaymentDetails('schoolfee',self.student)
-        self.assertEqual(payment.p_level, 100)
-        self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 40000.0)
+        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
+        self.assertEqual(payment.p_level, 100)
+        self.assertEqual(payment.p_session, 2004)
+        self.assertEqual(payment.amount_auth, 6666.0)
         self.assertEqual(payment.p_item, u'CERT1')
         self.assertEqual(error, None)
@@ -340,12 +365,12 @@
         # Add penalty fee.
         self.app['configuration']['2004'].penalty_ug = 99.0
-        error, payment = utils.setPaymentDetails('schoolfee',self.student)
-        self.assertEqual(payment.amount_auth, 40099.0)
+        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
+        self.assertEqual(payment.amount_auth, 6765.0)
 
         IWorkflowState(self.student).setState('returning')
-        error, payment = utils.setPaymentDetails('schoolfee',self.student)
+        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
         self.assertEqual(payment.p_level, 200)
         self.assertEqual(payment.p_session, 2005)
-        self.assertEqual(payment.amount_auth, 20099.0)
+        self.assertEqual(payment.amount_auth, 6765.0)
         self.assertEqual(payment.p_item, u'CERT1')
         self.assertEqual(error, None)
@@ -354,5 +379,5 @@
         self.assertEqual(payment.p_level, 100)
         self.assertEqual(payment.p_session, 2004)
-        self.assertEqual(payment.amount_auth, 34250.0)
+        self.assertEqual(payment.amount_auth, 1234.0)
         self.assertEqual(payment.p_item, u'CERT1')
         self.assertEqual(error, None)
Index: main/waeup.aaue/trunk/src/waeup/aaue/students/utils.py
===================================================================
--- main/waeup.aaue/trunk/src/waeup/aaue/students/utils.py	(revision 8746)
+++ main/waeup.aaue/trunk/src/waeup/aaue/students/utils.py	(revision 8753)
@@ -76,14 +76,7 @@
             amount = academic_session.maint_fee
         elif category == 'clearance':
-            try:
-                p_item = student['studycourse'].certificate.code
-            except (AttributeError, TypeError):
-                return _('Study course data are incomplete.'), None
-            if p_item in ('BEDCET', 'BIOEDCET', 'CHMEDCET', 'ISEDCET',
-                'MTHEDCET', 'PHYEDCET', 'ITECET', 'AGREDCET', 'HEEDCET'):
-                amount = 17250.0
-            else:
-                amount = 34250.0
-        elif category == 'schoolfee':
+            amount = academic_session.clearance_fee
+            p_item = student['studycourse'].certificate.code
+        elif category == 'schoolfee_1':
             try:
                 certificate = student['studycourse'].certificate
@@ -91,23 +84,52 @@
             except (AttributeError, TypeError):
                 return _('Study course data are incomplete.'), None
+            payment_allowed = False
             if student.state == CLEARED:
-                amount = getattr(certificate, 'school_fee_1', 0.0)
+                payment_allowed = True
+                amount = academic_session.school_fee_base
             elif student.state == RETURNING:
-                # In case of returning school fee payment the payment session
-                # and level contain the values of the session the student
-                # has paid for.
                 p_session, p_level = self.getReturningData(student)
-                amount = getattr(certificate, 'school_fee_2', 0.0)
-            elif student.is_postgrad and student.state == PAID:
-                # Returning postgraduate students also pay for the next session
-                # but their level always remains the same.
-                p_session += 1
-                amount = getattr(certificate, 'school_fee_2', 0.0)
+                initial_instalment_made = False
+                for key in student['payments'].keys():
+                    ticket = student['payments'][key]
+                    if ticket.p_category == 'schoolfee_1':
+                        initial_instalment_made = True
+                    if ticket.p_state == 'paid' and\
+                       ticket.p_category == 'schoolfee_2' and \
+                       ticket.p_item == p_item and \
+                       ticket.p_session == p_session-1: #  = current session
+                       payment_allowed = True
+                if not initial_instalment_made:
+                    payment_allowed = True
+                amount = academic_session.school_fee_base
+            else:
+                return _('Wrong state.'), None
+            if not payment_allowed:
+                return _('The previous 2nd school fee instalment '
+                         'has not yet been paid.'), None
+        elif category == 'schoolfee_2':
+            try:
+                certificate = student['studycourse'].certificate
+                p_item = certificate.code
+            except (AttributeError, TypeError):
+                return _('Study course data are incomplete.'), None
+            payment_allowed = False
+            for key in student['payments'].keys():
+                ticket = student['payments'][key]
+                if ticket.p_state == 'paid' and\
+                   ticket.p_category == 'schoolfee_1' and \
+                   ticket.p_item == p_item and \
+                   ticket.p_session == p_session:
+                   payment_allowed = True
+            if not payment_allowed:
+                return _('The 1st school fee instalment '
+                         'has not yet been paid.'), None
+            amount = academic_session.school_fee_base
         if amount in (0.0, None):
             return _(u'Amount could not be determined.'), None
         # Add session specific penalty fee.
-        if category == 'schoolfee' and student.is_postgrad:
+        if category == 'schoolfee_1' and student.is_postgrad:
             amount += academic_session.penalty_pg
-        elif category == 'schoolfee':
+        elif category == 'schoolfee_1':
             amount += academic_session.penalty_ug
         # Create ticket.
