Index: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/utils.py
===================================================================
--- main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/utils.py	(revision 17947)
+++ main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/utils.py	(revision 18034)
@@ -49,5 +49,5 @@
     PORTRAIT_CHANGE_STATES = (ADMITTED, CLEARANCE,)
 
-    REQUIRED_PAYMENTS_FRESH = {
+    REQUIRED_PAYMENTS_FRESH_SCIENCE = {
         'registration_fresh': 'Registration Fee (Fresh)',
         'book': 'Book Deposit',
@@ -55,6 +55,28 @@
         'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
         'municipal_fresh': 'Fresh Students Municipal Fee',
-        }
-
+        'matric': 'Matriculation Fee',
+        'waecneco': 'WAEC/NECO Verification',
+        'jambver': 'JAMB Verification Fee',
+        'health_insurance': 'Student Health Insurance',
+        'id_card': 'I.D. Card',
+        'medical_screening': 'Medical Screening Fees',
+        'science': 'Science Bench Fee',
+        }
+
+    REQUIRED_PAYMENTS_FRESH_NON_SCIENCE = {
+        'registration_fresh': 'Registration Fee (Fresh)',
+        'book': 'Book Deposit',
+        'develop': 'Development Fee',
+        'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
+        'municipal_fresh': 'Fresh Students Municipal Fee',
+        'matric': 'Matriculation Fee',
+        'waecneco': 'WAEC/NECO Verification',
+        'jambver': 'JAMB Verification Fee',
+        'health_insurance': 'Student Health Insurance',
+        'id_card': 'I.D. Card',
+        'medical_screening': 'Medical Screening Fees',
+        }
+
+    # all students (except PHM) returning
     REQUIRED_PAYMENTS_RETURNING = {
         'registration_return': 'Registration Fee (Returning)',
@@ -63,4 +85,44 @@
         'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
         'municipal_returning': 'Returning Students Municipal Fee',
+        'health_insurance': 'Student Health Insurance',
+        }
+
+
+    # all stdents (except PHM) final year
+    REQUIRED_PAYMENTS_FINAL = {
+        'registration_return': 'Registration Fee (Returning)',
+        'book': 'Book Deposit',
+        'develop': 'Development Fee',
+        'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
+        'municipal_returning': 'Returning Students Municipal Fee',
+        'health_insurance': 'Student Health Insurance',
+        'alumni': 'Alumni Fees',
+        'conv': 'Convocation Fees',
+        'clearance': 'Clearance Fees',
+        }
+
+    # PHM returning students
+    REQUIRED_PAYMENTS_RETURNING_PHARMACY = {
+        'registration_return': 'Registration Fee (Returning)',
+        'book': 'Book Deposit',
+        'develop': 'Development Fee',
+        'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
+        'municipal_returning': 'Returning Students Municipal Fee',
+        'health_insurance': 'Student Health Insurance',
+        'lab_support': 'Lab Support',
+        }
+
+    # PHM students final year
+    REQUIRED_PAYMENTS_FINAL_PHARMACY = {
+        'registration_return': 'Registration Fee (Returning)',
+        'book': 'Book Deposit',
+        'develop': 'Development Fee',
+        'parentsconsult': 'Parents Consultative Forum (PCF) Fee',
+        'municipal_returning': 'Returning Students Municipal Fee',
+        'health_insurance': 'Student Health Insurance',
+        'alumni': 'Alumni Fees',
+        'conv': 'Convocation Fees',
+        'clearance': 'Clearance Fees',
+        'lab_support': 'Lab Support',
         }
 
@@ -87,14 +149,34 @@
         return
 
-    def _requiredPaymentsMissing(self, student, session):
-        # Deactivated on 29/09/20 (don't know why)
-        return
-
+    def _is_payment_for_final(self, student):
+        studycourse = student['studycourse']
+        certificate = getattr(studycourse,'certificate',None)
+        current_level = studycourse.current_level
+        if None in (current_level, certificate):
+            return False
+        end_level = certificate.end_level
+        if current_level >= end_level-100:
+            return True
+        return False
+
+    def _collect_required_payment_items(self, student):
         if student.is_postgrad:
             rp = self.REQUIRED_PAYMENTS_PG
+        elif student.is_fresh and student.faccode in ('ENG', 'HSC', 'NAS', 'PHM'):
+            rp = self.REQUIRED_PAYMENTS_FRESH_SCIENCE
         elif student.is_fresh:
-            rp = self.REQUIRED_PAYMENTS_FRESH
+            rp = self.REQUIRED_PAYMENTS_FRESH_NON_SCIENCE
+        elif student.faccode == 'PHM' and self._is_payment_for_final(student):
+            rp = self.REQUIRED_PAYMENTS_FINAL_PHARMACY
+        elif student.faccode == 'PHM':
+            rp = self.REQUIRED_PAYMENTS_RETURNING_PHARMACY
+        elif self._is_payment_for_final(student):
+            rp = self.REQUIRED_PAYMENTS_FINAL
         else:
-            rp = self.REQUIRED_PAYMENTS_RETURNING
+            rp = REQUIRED_PAYMENTS_RETURNING
+        return rp
+
+    def _requiredPaymentsMissing(self, student, session):
+        # Has the required combi payment been made?
         for ticket in student['payments'].values():
             if ticket.p_category == 'required_combi'and \
@@ -102,4 +184,6 @@
                 ticket.p_state == 'paid':
                 return
+        # If not, check single payments
+        rp = self._collect_required_payment_items(student)
         cats_missing = deepcopy(rp)
         if len(student['payments']):
@@ -114,4 +198,16 @@
         return "%s must be paid before Tution Fee. Make either single payments or make a 'Required Combi Payment'." % ', '.join(
             cats_missing.values())
+
+    @property
+    def _all_required_payments(self):
+        return set(
+            self.REQUIRED_PAYMENTS_PG.keys()
+            + self.REQUIRED_PAYMENTS_FRESH_SCIENCE.keys()
+            + self.REQUIRED_PAYMENTS_FRESH_NON_SCIENCE.keys()
+            + self.REQUIRED_PAYMENTS_FINAL_PHARMACY.keys()
+            + self.REQUIRED_PAYMENTS_RETURNING_PHARMACY.keys()
+            + self.REQUIRED_PAYMENTS_FINAL.keys()
+            + self.REQUIRED_PAYMENTS_RETURNING.keys()
+            )
 
     def samePaymentMade(self, student, category, p_item, p_session):
@@ -158,7 +254,5 @@
             p_level = student['studycourse'].current_level
             p_current = True
-            if category in self.REQUIRED_PAYMENTS_FRESH.keys() \
-                + self.REQUIRED_PAYMENTS_RETURNING.keys() \
-                + ['schoolfee','schoolfee40','secondinstal'] \
+            if category in list(self._all_required_payments) + ['required_combi',] \
                 and student.state == RETURNING:
                 # In case of school fee or required sundry fee payments the
@@ -253,12 +347,8 @@
                 p_item += u'%s + ' % categories[cat]
             p_item = p_item.strip(' + ')
+
         elif category == 'required_combi':
-            if student.is_postgrad:
-                rp = self.REQUIRED_PAYMENTS_PG
-            elif student.is_fresh:
-                rp = self.REQUIRED_PAYMENTS_FRESH
-            else:
-                rp = self.REQUIRED_PAYMENTS_RETURNING
-            for cat in rp:
+            rp = self._collect_required_payment_items(student)
+            for cat in rp.keys():
                 fee_name = cat + '_fee'
                 cat_amount = getattr(academic_session, fee_name, 0.0)
@@ -268,4 +358,5 @@
                 p_item += u'%s + ' % rp[cat]
             p_item = p_item.strip(' + ')
+
         else:
             fee_name = category + '_fee'
